How to update a model TextField based on a function output - django-models

I have a PIL function that checks the uploaded image resolution and resizes it to either a fulscreen resolution or banner resolution then saves it to the database. Now I need to add a model textfield that saves the values "fullscreen" or "banner" to the database table when the picture is saved. I have added the field to the model but I don't know where and how to update this.

You can bind your attribute that is to be derived to a function.
Example: I have a Person model with fields fname and lname.
I can derive a function :
class Person(models.Model):
lname = models.CharField(max_length=500, blank=False)
fname = models.CharField(max_length=500, blank=False)
def fullname(self):
return "%s %s"%(self.fname,self.lname)
name = property(fullname)
Whenever I do person.name it will actually return a name by combining fname and lname.

Related

Got AttributeError when attempting to get a value for field `people` on serializer `commentsSerializer`

I am building a blog website and I am using Django rest framework
I want to fetch top 2 comments for a particular post along with their related data such as user details.
Now I have user details in two models
User
People
and the comments model is related to the user model using foreign key relationship
Models ->
Comments
class Comment(models.Model):
comment = models.TextField(null=True)
Created_date = models.DateTimeField(auto_now_add=True)
Updated_date = models.DateTimeField(auto_now=True)
post = models.ForeignKey(Post, on_delete=models.CASCADE,
related_name='comments_post')
user = models.ForeignKey(User, on_delete=models.CASCADE,
related_name='comments_user')
The People model is also connected to the user model with a foreign key relationship
People Model ->
class People(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,related_name='people')
Name = models.CharField(max_length=255,null=True)
following = models.ManyToManyField(to=User, related_name='following', blank=True)
photo = models.ImageField(upload_to='profile_pics', blank=True,null=True)
Phone_number = models.CharField(max_length=255,null=True,blank=True)
Birth_Date = models.DateField(null=True,blank=True)
Created_date = models.DateTimeField(auto_now_add=True)
Updated_date = models.DateTimeField(auto_now=True)
for fetching the comments I am using rest-framework and the serializers look like this
class UserSerializer(serializers.Serializer):
username = serializers.CharField(max_length=255)
class peopleSerializer(serializers.Serializer):
Name = serializers.CharField(max_length=255)
class commentsSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
comment = serializers.CharField(max_length=255)
Created_date = serializers.DateTimeField()
user = UserSerializer()
people = peopleSerializer()
The query to fetch the comments look like this ->
post_id = request.GET.get('post_id')
comments = Comment.objects.filter(post_id=post_id).select_related('user').prefetch_related('user__people').order_by('-Created_date')[:2]
serializer = commentsSerializer(comments, many=True)
return Response(serializer.data)
I am getting this error ->
Got AttributeError when attempting to get a value for field `people` on serializer `commentsSerializer`. The serializer field might be named incorrectly and not match any attribute or key on the `Comment` instance. Original exception text was: 'Comment' object has no attribute 'people'.
Unable to find a way out.
The source is user.people, not people, so:
class commentsSerializer(serializers.Serializer):
# …
people = peopleSerializer(source='user.people')
In the .select_related(…) [Django-doc] to can specify user__people: this will imply selecting user and will fetch the data in the same query, not in an extra query as is the case for .prefetch_related(…) [Django-doc]:
post_id = request.GET.get('post_id')
comments = Comment.objects.filter(
post_id=post_id
).select_related('user__people').order_by('-Created_date')[:2]
serializer = commentsSerializer(comments, many=True)
return Response(serializer.data)
Note: normally a Django model is given a singular name, so Person instead of People.
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
Note: normally the name of the fields in a Django model are written in snake_case, not PascalCase, so it should be: created_date instead of Created_date.

How can i add data into my model which is many to many field for another model

This is just a example of my models and form. my question is how i can save data in my both models only using one form. i wanted to save data through my Book Form() where in book model i have created a many to many field from Author Model and if i used this form then he is telling me to first add data in author model then only select and save data in book model. through my template i wanted to render fields from my form as author title , name , date of birth and book name and when user enter all the details it should be saved in respective models only.
TITLE_CHOICES = (
('MR', 'Mr.'),
('MRS', 'Mrs.'),
('MS', 'Ms.'),
)
class Author(models.Model):
name = models.CharField(max_length=100)
title = models.CharField(max_length=3, choices=TITLE_CHOICES)
birth_date = models.DateField(blank=True, null=True)
def __str__(self):
return self.name
class Book(models.Model):
name = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
class BookForm(ModelForm):
class Meta:
model = Book
fields = ['name', 'authors']

how to change the verbose_name or use original field name in django-taggit tag field

I am using django-taggit for one of my projects and as per the documentation I did the following in the model that i want to use tags / keywords in.
models.py
from taggit.managers import TaggableManager
class SomeModel(models.Model):
title = models.CharField(max_length=15)
description = models.TextField()
keywords = TaggableManager()
I am using a ModelForm form for the above model and the label's text for the keywords field shows up as "Tags" instead of "Keywords".
How can i have django-taggit use the original field name ??
Just opened up the TaggableManager definition to check this.
class TaggableManager(RelatedField):
def __init__(self, verbose_name=_("Tags"),
help_text=_("A comma-separated list of tags."), through=None, blank=False):
So to set the verbose_name simply initialize the manager as:
TaggableManager(verbose_name="keywords")

Django: Single model for multiple tables

I have a main table
Slideshow
then a site specific table that captures a few extra details for that site.
Site1_Slideshow
In a web app (specific to a site) i want a single model i.e. Slideshow that combines the 2 tables above.
Currently i have the code below, but i dont think this is correct. I cant do things like
s = Slideshow.objects.get(slideshowId=1) as Slideshows only has the properties featurecategory and slideshow. So how can i have an model called Slideshow that is composed of these 2 tables but looks like it was a single db table.
class SlideshowAbstract(models.Model):
slideshowid = models.IntegerField(primary_key=True, db_column=u'SlideshowId') # Field name made lowercase.
headline = models.TextField(db_column=u'Headline') # Field name made lowercase.
class Meta:
db_table = u'Slideshow'
class Slideshow(models.Model):
slideshow = models.OneToOneField(SlideshowAbstract, primary_key=True,db_column=u'SlideshowId')
def __unicode__(self):
return self.slideshow.headline
class Meta:
db_table = u'Site1_Slideshow'
Think i found the solution.
On the Site1_Slideshow you need to add a column for django to use, that i presume is always the same as primary key value.
Its name is SlideshowAbstract_ptr_id
Once that is added you can change the Slideshow model to be
class Slideshow(SlideshowAbstract):
featureCategory = models.ForeignKey(Featurecategory,db_column=u'FeatureCategoryId')
def __unicode__(self):
return self.headline
class Meta:
db_table = u'Site1_Slideshow'
So doable but not the nicest if you are not doing "model first" and already have the schema. Would be good to be able to override the name of the _ptr_id column.
I did try adding the following to Slideshow too see if i could map this ptr col to the primary key
slideshowabstract_ptr_id = models.IntegerField(primary_key=True, db_column=u'SlideshowId')
but no cigar.
I havent tested inserts either but ...objects.all() works

Django form on the model

I have Guest model in my app:
class Guest(models.Model):
event = models.ForeignKey(Event, related_name='guests')
contact = models.ForeignKey(Contact, related_name='guests')
attending_status = models.CharField(max_length=32, choices=ATTENDING_CHOICES, default='no_rsvp')
number_of_guests = models.SmallIntegerField(default=0)
comment = models.CharField(max_length=255, blank=True, default='')
updated = models.DateTimeField(blank=True, null=True)
Event and Contact I fill up by myself in Admin when creating a guest. On the site all I want is a guest to fill up the form where he refreshes his attending status, points out number of guests and leaves a comment.
class RSVPForm(forms.Form):
attending = forms.ChoiceField(choices=VISIBLE_ATTENDING_CHOICES, initial='yes', widget=forms.RadioSelect)
number_of_guests = forms.IntegerField(initial=0)
comment = forms.CharField(max_length=255, required=False, widget=forms.Textarea)
How can I save the changes to the Guest model instance? How can I access the guest's id when saving the changes to his profile?
You are probably looking for Django's ModelForms. Instead of subclassing forms.Form in your RSVPForm class, you should subclass forms.ModelForm. Then you can use the features of the model form class to help you achieve what you want (hide some fields, etc). An example is below:
class RSVPForm(forms.ModelForm):
class Meta:
model = Guest
fields = ('attending_status', 'number_of_guests', 'comment')
This will do essentially what you want, but you will need to remember to provide an instance keyword argument to the form constructor in your view function. This argument is the instance of the Guest model you will be updating with the form.
form = RSVPForm(instance=guest_object)
Now calls to the form.save() method will automatically save the new data to this Guest object instance. You just need to make sure that you always pass the instance keyword argument, even when using request.POST:
form = RSVPForm(request.POST, instance=guest_object)

Resources