I have some model where there are date field and CharField with choices New or Done, and I want to show some message for this model objects in my API views if 2 conditions are met, date is past and status is NEW, but I really don't know how I should resolve this.
I was thinking that maybe there is option to make some field in model that have choices and set suitable choice if conditions are fulfilled but I didn't find any information if something like this is possible so maybe someone have idea how resolve this?
You need override the method save of your model. An overrided method must check the condition and show message
You may set the signal receiver on the post_save signal that does the same like (1).
Related
Is there a way I can access the form that caused a post_save?
The use case is that I have a field (a checkbox) that isn't attached to a particular model, but it's an extra field in the form itself.
I want to know whether the field was checked or unchecked when the form got saved and the model stored, and imho the post_save signal is a good place to put the logic that should process that extra field.
I'm also open to suggestions where else I could put that piece of code.
post_save won't know anything about any form that might have caused the model change.
If you want to access that checkbox value you need to do it in the form class itself. I would probably override the clean() method of the form, and check for the checkbox value in cleaned_data['checkbox_field'] there, and then do whatever you need to with it.
I'm creating a UserProfile model where users can add as many or as few images to their profile as they wish. I've considered using an Image model like so:
class Image(models.Model):
related_profile = models.ForeignKey(UserProfile) # UserProfile is the name of the model class
user_picture = models.ImageField(upload_to=get_user_img, blank=True, null=True, height_field='height_field', width_field='width_field')
When somebody visits their UserProfile then all of their Image objects will be displayed; however when I want to edit the UserProfile (i.e. delete an image or two) but am unable to do this.
The 'instance' doesn't want to return more than one Image object to edit as I get error:
get() returned more than one Image -- it returned 2!
There's a similar question like this which suggested filter() as opposed to get() here django - get() returned more than one topic
though this uses a ManyToMany relationship, and the solution didn't work for my error.
Does anybody know any good ways to restructure this so that I can edit each model object from the same page (so not returning the aforementioned error)?
Like the title suggests, I'm wondering if it's possible to store a set of images as a list within one field of the UserProfile model because that's a potential idea.
You are on the right track. The Model.objects.get() method expects the query result to be one row (instance), which is then returned. However in your case the UserProfile can have any number of related Image's. So you need to iterate through the (possibly) multiple results you are going to get back from your query, and do something with each one. More like:
# there is only ONE UserProfile per userid.. that is to say, userid is a
# unique key.. so I can use get() to fetch it
profile = UserProfile.objects.get(userid=the_userid)
# now I need to get each image
for image in Image.objects.filter(user_profile=profile):
# do something with image....
If you only need the Image instances and don't need the UserProfile instance, then you can shorten this with a join:
for image in Image.objects.filter(user_profile__userid=the_userid):
# do something with image....
I should add that this has nothing to do with images, but applies any time you fetch data from the database using Django. Any query that has multiple rows needs to be done in this way.
I want to do some custom actions before a user is created. and I thought of using the pre_save signal for that. And in case one of those action would raise an exception stop the transaction, abort creating the user etc.
Is this the way to go? would it abort the save if something fails in this step (this is the required behavior) I suspect so but couldn't find docs about it.
What is the best practice for getting the future user.id. from my understanding it doesn't exists yet in pre-save but I need it as input for some of the extra custom actions.
Thanks
From the docs:
There's no way to tell what the value of an ID will be before you call
save(), because the value is determined by your database, not by
Django.
So if your pre-save processing requires the user.id, I am afraid this is not possible.
Here is the two part answer:
Yes, raising an exception in the pre_save() signal will abort the call to the save() method. For example, I did this in my pre_save():
if SOME_TEST:
raise exceptions.ParseError(detail="I reject your data. Here is why.")
Note: This was using the DRF exceptions, but I will assume you know how to raise whatever exception you prefer.
You could use the post_save() signal to get the id AFTER the save() method. But if that will not work for you, then below is my original explanation of some tactics to do what you want in the pre_save():
In the pre_save you can access User.objects.all() (if you import the User model, of course). If you are using the standard User model then the User.id value is AUTO INCREMENT. So if you NEED to know what the value WILL be for the new user, just get the highest User.id currently in the database (ie: the id of the last user created). Here is a simple query to do this:
last_user = User.objects.latest('id')
Then of course, last_user.id will give you the value of the id for the last user created and if you add one to that you will have the next user id. Of course, if you have a busy site you may have some problems with simultaneous user creation. The risk is that this value is received by two (or more) User creation attempts and one (or more) of them ends up wrong.
Of course, you can always set another field to be primary_key=True and this will replace the id field on the model. Then you can devise any sort of indexing mechanism that you can dream up! You could use a hash value of a unique characteristic. For example: The User.username has a Unique constraint, you could hash or hex encode that as a numeric ID to pre-determine the User.id. Or you could leave the id field in place and set it manually in the pre_save by assigning a value to obj.id. It could be anything you want. Even a hash value!
I'm basically building a very trivial form. Let's stick to the books/publisher examples given in the django tutorials and build upon that.
I have a user login to the web app, at which point the first thing they can do is click on a publisher. This publisher then gets saved for their session. Upon that I take them to a create book form. In there I embed the the publisher's id from the database into a hidden field.
Upon the user submitting an HTTP POST, I do something like:
mybookform = BookForm(request.POST)
if mybookform.is_valid():
abook = mybookform.save(commit=False)
abook.publisher_id = request.POST['publisher_id']
mybookform.save()
Yes there's a few naive things done here, such as blindly grabbing the publisher_id and verifying if it's indeed a real publisher id, amongst other security issues. Let's just not pay attention to that for the moment.
My question is, is there a better way of handling this? Although hypothetically this example doesn't make logistical sense, in my particular app the example actually makes sense. The problem is I get a ValueError exception saying publisher_id needs to be a Publisher instance.
Now I can easily retrieve a publisher instance with Publisher.objects.filter(id=..) and use that instead. The question is, is it really necessary? Can I avoid the additional query to the database and somehow update this form instance in a more 'elegant' fashion?
Also, is it possible to somehow embed the publisher in a hidden field so that I do not need to do mybookform.save(commit=False) and just do mybookform = BookForm(request.POST) followed by mybookform.save() immediately?
Retrieving the instance of the publisher does protect against client-side changes that might reference a completely invalid publisher.
To your second question, yes you can include that field as a hidden field by overriding the field in the ModelForm with the approriate form field setting the widget to HiddenInput.
There is no better way to do this.
I would use the get_object_or_404 function for this.
And yes, you can prevent this to be modified by the user by setting the model field to editable=False,
I am using 0.97-pre-SVN-unknown release of Django.
I have a model for which I have not given any primary_key. Django, consequently, automatically provides an AutoField that is called "id". Everything's fine with that. But now, I have to change the "verbose_name" of that AutoField to something other than "id". I cannot override the "id" field the usual way, because that would require dropping/resetting the entire model and its data (which is strictly not an option). I cannot find another way around it. Does what I want even possible to achieve? If you may suggest any alternatives that would get me away with what I want without having to drop the model/table, I'd be happy.
Hmm... and what about explicitly write id field in the model definition? Like this for example:
class Entry(models.Model):
id = models.AutoField(verbose_name="custom name")
# and other fields...
It doesn't require any underlying database changes.
Look into the command-line options for manage.py; there's a command to dump all of the model data to JSON, and another command to load it back in from JSON. You can export all of your model data, add your new field to the model, then import your data back in. Just make sure that you set the db_column option to 'id' so you don't break your existing data.
Edit: Specifically, you want the commands dumpdata and loaddata.