Got AttributeError when attempting to get a value for field `email` on serializer `UserSerializer` - serialization

Creating Django REST FRamework API. Using Abstract User and email is the default logging parameter using.
AttributeError at /post/
Got AttributeError when attempting to get a value for field email on serializer UserSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the Post instance.
Original exception text was: 'Post' object has no attribute 'email'.
class PostSerializer(ModelSerializer):
category = ReadOnlyField(source='category.name')
author = UserSerializer(source='user.email')
#question = serializers.CharField(source='question.text', read_only=True)
class Meta:
model = Post
fields = '__all__'
class User(AbstractUser):
username = models.CharField("Username", max_length=50, unique=True)
email = models.EmailField("Email Address", max_length=254, unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username', 'first_name', 'last_name']
class Post(models.Model):
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published'),
)
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250, unique_for_date='publish')
author = models.ForeignKey(User, related_name='posts', on_delete=models.CASCADE, to_field='email')
category = models.ForeignKey(Category, related_name='categorys', on_delete=models.CASCADE)
body = models.TextField()
image = models.ImageField(upload_to='blog/%Y/%m/%d', blank=True)
publish = models.DateTimeField(default=timezone.now)
rating = models.IntegerField("Rumor Rate", validators=[MaxValueValidator(5), MinValueValidator(0)], default=1, null=True)
created = models.DateTime[![enter image description here][1]][1]Field(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')

I suppose you want to return the author's email in the author field when you request the Post endpoint. You may also convert the author field in the serializer to a ReadOnlyField (as category) and specify source='author.email', since your model foreign key is named like that:
class PostSerializer(ModelSerializer):
category = ReadOnlyField(source='category.name')
author = ReadOnlyField(source='author.email')
# ...

Related

Cannot resolve keyword into field error while using drf model serializer and search_fields within field set?

SerializerClass:
class VacancySerializer(serializers.ModelSerializer):
organization_small_name = serializers.CharField(source='organization.short_name', read_only=True)
class Meta:
model = Vacancy
fields = ['organization', 'description', 'specs', 'type', 'publication_date',
'is_published', 'withdrawal_data', 'organization_small_name', ]
read_only_fields = ['publication_date', 'is_published', 'withdrawal_data',]
ViewSet:
class VacancyViewSet(viewsets.ModelViewSet):
queryset = Vacancy.objects.all()
serializer_class = VacancySerializer
filter_backends = [filters.SearchFilter]
search_fields = ['organization_small_name']
...
Model:
class Vacancy(models.Model):
organization = models.OneToOneField(DictOrganization, on_delete=models.CASCADE, related_name='vacancies')
description = models.TextField('Описание')
specs = models.ManyToManyField(DictSpec, blank=True)
type = models.CharField('Тип', max_length=20, choices=VacancyType.choices(), default=VacancyType.PRACTICE.value)
publication_date = models.DateField('Дата публикации', null=True, blank=True)
is_published = models.BooleanField('Опубликовано', default=False)
withdrawal_data = models.DateField('Дата снятия с публикации', null=True, blank=True)
My goal is to make API search by 'organization_small_name' field
that is in VacancySerializer.
Server runs successfully, but as soon as i add ?search parameter, i get next error:
Why it doesn't recognize 'organization_small_name' field, even thought it is decribed in serializer, and how can i fix it?

Edit many-to-many relationship in Flask-SQLAlchemy withg WTForms

I struggle handling a many-to-many relationship (here: users and groups) in a Flask form. My database structure (simplified) looks as follow:
association_user_group = db.Table(
'association_user_group',
db.Column('user_id', db.Integer, db.ForeignKey('user.id')),
db.Column('group_id', db.Integer, db.ForeignKey('group.id'))
)
class Group(db.Model):
__tablename__ = 'group'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(32))
users = db.relationship(
'User',
secondary=association_user_group,
backref=db.backref('groups', lazy='dynamic'))
class User(UserMixin, db.Model):
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), index=True, unique=True)
#property
def group_ids(self):
return [u.id for u in self.groups]
To handle a form that allows an admin to edit the users, I have:
class MultiCheckboxField(SelectMultipleField):
widget = widgets.ListWidget(prefix_label=False)
option_widget = widgets.CheckboxInput()
class UserEditForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Password')
groups = MultiCheckboxField('Groups', coerce=int)
submit = SubmitField('Apply changes')
and the following route:
#bp.route('/user_edit/<int:id>', methods=['GET', 'POST'])
#login_required
#admin_required
def user_edit(id):
user = User.query.get(id)
if request.method == 'GET':
form = UserEditForm(obj=user)
form.groups.data = [grp.id for grp in user.groups]
else:
form = UserEditForm(request.form)
form.groups.choices = [(grp.id, grp.name) for grp in Group.query.all()]
if form.validate_on_submit():
#form.populate_obj(user) <-- does not work
user.username = form.data.username
if form.password.data != '':
user.set_password(form.password.data)
# how do I update the 'groups'?
db.session.add(user)
db.session.commit()
return "Data={}".format(form.data)
The database and form works, but I am unable to copy the groups form content back to the database. Ideally, I'd be able to 'populate back' the form content to the User object, but this fails because of the groups (and I think it might also fail with the password field that is empty if no change is requested).
I then tried to delete all groups from user and re-add the ones I want, but did not figure out a reasonable way to achieve this. I am able to add an group membership with user.groups.append(grp) where grp is the corresponding database object. I also am able to remove a group membership in the same way, but given the group ids this would mean looping through all group ids, retrieving the group object, and then using this object to invoke the remove method, which seems overly complicated.
Overall, I suspect that I attempt to implements all this in a far too awkward way...

How to get an object with a similar tag using django

I have an object (a blogpost) which can have multiple tags in django. I'm trying to get related objects with one or more of these same tags.
For example: You have a blogpost with a few tags, like 'food', 'drinks' and 'restaurants'. When you open this blogpost, there are displayed some 'related' blogposts (meaning they share one or more tags). An example of such a related blogpost would have the tags: 'soda', 'lemonade' and 'drinks'.
Here is my view:
instance = get_object_or_404(Blog, id=id)
tags = instance.tags.values()
related = []
for x in tags: #to put all the tags in an array
related.append(x['name'])
for a in Blog.objects.raw('SELECT * FROM "blog_table" WHERE related in "blog_table"."tags"'):
print (a.name) #this should display the name of all the related blogposts (probably including itself)
Here are my models:
class Tag(models.Model):
name = models.CharField(max_length=500)
number = models.IntegerField(null=True, blank=True)
def __str__(self):
return str(self.number) + ' ' + self.name
class Blog(models.Model):
name = models.CharField(null=False, max_length=500, verbose_name='title of blogpost', unique=True)
body = models.TextField(null=False, verbose_name='body of the blogpost')
tags = models.ManyToManyField(Tag, blank=True, null=True)
def __str__(self):
return self.name
To get the blogs that have similar instance tag, you can do this:
tags = instance.tag.all()
for tag in tags:
print(Blog.objects.filter(tags=tag))

Odoo, can't have two different siblings objects in the same view

I have a class named detail_base, and two other classes name flight_detail and tour_detail, the last two classes inherits from the first one, like this:
class DetailBase(models.Model):
_name = 'detail_base'
fee = fields.Monetary('Fee')
passenger = fields.Char('Passenger')
class FlightDetail(models.Model):
_name = 'flight_detail'
_inherits = 'detail_base'
passport = fields.Char('Passport')
class TourDetail(models.Model):
_name = 'tour_detail'
_inherits = 'detail_base'
age = fields.Integer('Tourist Age')
The problem is when I call the flight_detail and tour_detail in the same view, the browser can't handle the common attributes of both classes, If I assign 5 to tour_detail.fee, that number will be stored into flight_detail.fee.
It seems the problem is related to the attributes with the same name of different objects being siblings.
I will appreciate any help.
You should either use _inherit
class DetailBase(models.AbstractModel):
_name = 'detail_base'
fee = fields.Monetary('Fee')
passenger = fields.Char('Passenger')
class FlightDetail(models.Model):
_name = 'flight_detail'
_inherit = 'detail_base'
passport = fields.Char('Passport')
class TourDetail(models.Model):
_name = 'tour_detail'
_inherit = 'detail_base'
age = fields.Integer('Tourist Age')
which should either create 3 database tables (detail_base as Model) or 2 database tables (AbstractModel).
Or you use _inherits like:
class DetailBase(models.Model):
_name = 'detail_base'
fee = fields.Monetary('Fee')
passenger = fields.Char('Passenger')
class FlightDetail(models.Model):
_name = 'flight_detail'
_inherits = {'detail_base': 'base_id'}
passport = fields.Char('Passport')
base_id = fields.Many2one('detail_base', required=True, ondelete='cascade')
class TourDetail(models.Model):
_name = 'tour_detail'
_inherit = {'detail_base': 'base_id'}
age = fields.Integer('Tourist Age')
base_id = fields.Many2one('detail_base', required=True, ondelete='cascade')
That will create 3 tables, and fee and passenger will be stored in detail_base table. Odoo will get it from there, because it is a sort of delegation inheritence.
use inherit:
1- inherit without _name :
inherit = 'model.name'
new_field = fields...
this add this field to the model.name
2- inherit with _name:
inherit = 'model.name'
_name = 'new.model'
here will create a new tabel in database with the same structure of model.name.
inherits: The delegation inheritance.
best example is res.users and res.partners user is a partener so when we create a res.users record we must create a res.partener that hold commun field like name, email, address ... and information related to users like passowrd and login are stored in res.users model and with type of inheritence you can access field of res.partener directly without having to create a related field. you can do user_record.name or .email or .address this will not be a problem.
i like to think of it as one2one relation.
_inherits = {model.name : many2one_field_id }
_name = 'new.model'
# m2o field should be required and ondelete = cascade
many2one_field_id = fields.Many2one('model.name', string='Label', required=True, ondelete="cascade")
so when you create a record of new.model all field that are in model.name will be stored in model.name.

Issue with complex Django join query

I can't find a valid way with Django OMR in order to get : ( a raw query is also fine )
the Sites.sitename which made the Analysis where (Analysi_Items.name='somename' and Analysis_Items.value='somevalue') and (Analysi_items_name='somename' and Analysis_Items.value='somevalue') and (Analysis_items.name='somename' and Analysis_Items.value='somevalue').
class Sites(models.Model):
region = models.CharField(max_length=1000)
province = models.CharField(max_length=1000)
sitename = models.CharField(max_length=1000, primary_key=True)
class Meta:
verbose_name_plural = "Sites"
def __unicode__(self):
return self.sitename
class Analysis_Items(models.Model):
code = models.ForeignKey('Analysis')
name = models.CharField(max_lenght=100)
value = models.CharField(max_length=20)
class Meta:
verbose_name_plural = "Analysis Type"
class Analysis(models.Model):
date = models.DateField()
site = models.ForeignKey('Sites')
def __unicode__(self):
return str(self.date)
class Meta:
verbose_name_plural = "Analysis"
Hope this is clear enough. thank you in advance!
Site.objects.filter(analysis__analysis_items__name='some_name', analysis__analysis_items__value='some_value')
You can keep adding additional parameters in the same keep AND'ing them all together.