I'm quite new to Python and Django. I'm setting up a new model class and I'm able to add appointments on the admin page, but here's the strange thing:
I used to have a DateTimeFiled, which I changed to a separate DateField and a TimeField. But now I see neither my DateField nor my TimeField. Why is that, I don't understand it. I've done the migration, everything looks right.
This is my model class:
class Appointment(models.Model):
patient = models.ForeignKey(User, related_name="appointment_patient", on_delete=False)
date = models.DateField(auto_now=True)
start_time = models.TimeField(auto_now=True)
duration = models.DurationField(default=timedelta(minutes=30))
Before I made this change every property came out right, but now this happens:
auto_now automatically updated with timezone.now() whenever the model object is saved also its not editable. So its not necessary to display them in the template. That is why adminsite omits this field or does not show it. Please see the documentation for more details. If you want to display this field then add it readonly_fields. For example:
class YourModelAdmin(admin.ModelAdmin):
readonly_fields=('start_time',)
Update
If you want to add default value to DateField, try like this:
import datetime
# in models
state_date = models.DateField(default=datetime.date.today) # without parenthesis
Related
Sorry for the dumb question but I can't figure it out.
I have a class based view for a form. I like to make some changes if the request.user is equal with something.
I used before in some other views request.user.profile.leader that gives me a boolean answer. Thats OK.
Now in this class based view I like to use a very similar stuff but with another model like this: request.user.trust.group but it gives me nothing. What am I doing wrong?
If you haven't customized your user model, then profile will appear on it as a reverse descriptor of an one-to-one field on another model (by way of related_name having been set or inferred), i.e. you have something like
class Profile(Model):
user = models.OneToOneField(User, related_name="profile")
leader = models.BooleanField(...)
somewhere.
If you expect a trust field to be there, then you'd need something similar:
class Trust(Model):
user = models.OneToOneField(User, related_name="trust")
group = ...
On the other hand, if you do have an entirely custom user model, then those attributes could appear directly on it:
class CustomUser(AbstractBaseUser):
profile = models.ForeignKey(Profile, ...)
trust = models.ForeignKey(Trust, ...)
I have a model that has a many to many relationship to another model.
I am trying to update the many to many relationship on save, but nothing is being added.
Creating a new Flight via the Python Interpreter, saving it, and then running the loop I have in the 'save' method adds the correct lanes to the many to many relationship.
What am I missing in the overridden save method?
class Flight(models.Model):
number_of_lanes = models.PositiveSmallIntegerField()
start_time = models.TimeField()
lanes = models.ManyToManyField(Lane, blank=True)
tournament = models.ForeignKey('Tournament')
def __unicode__(self):
return u'Lanes: %s | Start: %s' % (self.number_of_lanes, self.start_time)
def save(self, *args, **kwargs):
super(Flight, self).save(*args, **kwargs)
for i in range(1, self.number_of_lanes+1):
lane = Lane.objects.get(id=i)
self.lanes.add(lane)
Here is the Console snippet from where I tested it:
>>> flight = Flight()
>>> flight.number_of_lanes=5
>>> flight.start_time='8:30'
>>> flight.tournament=t
>>> flight.save()
>>> flight.lanes.all()
[<Lane: 1>, <Lane: 2>, <Lane: 3>, <Lane: 4>, <Lane: 5>]
Edit:
Brief update on where I am on this.
The save method works within the console. The first time I tested it, I forgot to reload the Django shell. The many to many relationship is still not being created when adding from the admin page.
If the overridden save method works within the shell, shouldn't it work on the Django admin page?
You should take a look at the following article. It basically describes that when you save a model through the admin forms, it isn't an atomic transaction.
The main object is saved first, then the M2M is cleared and the new
values set to whatever came out of the form. So if you are in the
save() of the main object you are in a window of opportunity where the
M2M hasn't been updated yet. In fact, if you try to do something to
the M2M, the change will get wiped out by the clear().
Hello,
I have bound a ModelForm to one of my model that contains a ForeignKey to another model everything driven by a CreateView. What I want to achieve is to create the model object corresponding to the foreign key if it doesn't exist before the form is overall validated and the final object created in database.
Below the models I use:
class UmsAlerting(models.Model):
alert_id = models.IntegerField(primary_key=True, editable=False)
appli = models.ForeignKey('UmsApplication')
env = models.ForeignKey('UmsEnvironment')
contact = models.ForeignKey('UmsContacts')
custom_rule = models.ForeignKey('UmsCustomRules', null=True, blank=True)
class UmsApplication(models.Model):
appli_id = models.IntegerField(primary_key=True)
trigram_ums = models.CharField(max_length=4L)
class UmsContacts(models.Model):
contact_id = models.IntegerField(primary_key=True)
mail_addr = models.CharField(max_length=100L)
class UmsEnvironment(models.Model):
env_id = models.IntegerField(primary_key=True)
env_name = models.CharField(max_length=5L)
The model bound to the form is UmsAlerting. The model object I want to create if it doesn't exist is UmsContacts. I managed to use the field's clean method in my ModelForm of the contact field and use the get_or_create method like below:
def clean_contact(self):
data = self.cleaned_data['contact']
c, _ = UmsContacts.objects.get_or_create(mail_addr=data)
return c
It perfectly works when the contact is already in the database but when it needs to be created my form return a ValidationError on the contact field saying "This field cannot be null". If I submit the same form a second time without changing anything the UmsAlerting object is well created with no validation error.
My guess is that, for a reason I don't get, when get_or_create is used to create a UmsContacts object it cannot be used to create the new UmsAlerting object. So in clean_contact method the get is working and returns the UmsContacts object but the create part doesn't. It'd be like the UmsContacts object is saved when the whole form is validated but not before as I'd want it to.
Anyone could help me find out what is the problem ? Is using the clean method not the best idea ? Is there another strategy to use to take around this problem ?
Thanks in advance for your help.
It's probably because the object you are creating expects value for contact_id. If you use contact_id field for just setting object id -then you do not have to create it at all. Django takes care of Id's automatically.
Also. field clean method should return cleaned data not object. That creates whole lot more problems on its own.
I have a model such as the following:
class Item(models.Model):
name = models.CharField(max_length=150)
created = models.DateTimeField(auto_now_add=True)
the admin class is the following:
class ItemAdmin(admin.ModelAdmin):
list_display = ('name', 'created')
the created field does not seem to exist
Is there some basic Django knowledge that I am missing or have forgotten?
When you say the field does not exist, do you mean that it is not showing on the admin change form? This is expected behaviour when using auto_now_add. If you want the field to get a default value on creation but still be editable, use default=datetime.datetime.now instead.
Strange. I tried out your example and it worked perfectly well (Django 1.2.1, Python 2.6.2)
Can you verify that:
The field exists in the database (fire a SQL query perhaps)
Check your admin.py (again) for any differences.
Update
#Daniel's answer is more likely to help the OP.
Just make sure not to forget registering the ItemAdmin in admin.py:
admin.site.register(Item, ItemAdmin)
However, the 'created' field would only be displayed in the Item's list page, as well as if you add an additional field such as:
updated = models.DateTimeField(auto_now=True)
I have a couple of models in django which are connected many-to-many. I want to create instances of these models in memory, present them to the user (via custom method-calls inside the view-templates) and if the user is satisfied, save them to the database.
However, if I try to do anything on the model-instances (call rendering methods, e.g.), I get an error message that says that I have to save the instances first. The documentation says that this is because the models are in a many-to-many relationship.
How do I present objects to the user and allowing him/her to save or discard them without cluttering my database?
(I guess I could turn off transactions-handling and do them myself throughout the whole project, but this sounds like a potentially error-prone measure...)
Thx!
I would add a field which indicates whether the objects are "draft" or "live". That way they are persisted across requests, sessions, etc. and django stops complaining.
You can then filter your objects to only show "live" objects in public views and only show "draft" objects to the user that created them. This can also be extended to allow "archived" objects (or any other state that makes sense).
I think that using django forms may be the answer, as outlined in this documentation (search for m2m...).
Edited to add some explanation for other people who might have the same problem:
say you have a model like this:
from django.db import models
from django.forms import ModelForm
class Foo(models.Model):
name = models.CharField(max_length = 30)
class Bar(models.Model):
foos = models.ManyToManyField(Foo)
def __unicode__(self):
return " ".join([x.name for x in foos])
then you cannot call unicode() on an unsaved Bar object. If you do want to print things out before they will be saved, you have to do this:
class BarForm(ModelForm):
class Meta:
model = Bar
def example():
f1 = Foo(name = 'sue')
f1.save()
f2 = foo(name = 'wendy')
f2.save()
bf = BarForm({'foos' : [f1.id, f2.id]})
b = bf.save(commit = false)
# unfortunately, unicode(b) doesn't work before it is saved properly,
# so we need to do it this way:
if(not bf.is_valid()):
print bf.errors
else:
for (key, value) in bf.cleaned_data.items():
print key + " => " + str(value)
So, in this case, you have to have saved Foo objects (which you might validate before saving those, using their own form), and before saving the models with many to many keys, you can validate those as well. All without the need to save data too early and mess up the database or dealing with transactions...
Very late answer, but wagtail's team has made a separate Django extension called django-modelcluster. It's what powers their CMS's draft previews.
It allows you to do something like this (from their README):
from modelcluster.models import ClusterableModel
from modelcluster.fields import ParentalKey
class Band(ClusterableModel):
name = models.CharField(max_length=255)
class BandMember(models.Model):
band = ParentalKey('Band', related_name='members')
name = models.CharField(max_length=255)
Then the models can be used like so:
beatles = Band(name='The Beatles')
beatles.members = [
BandMember(name='John Lennon'),
BandMember(name='Paul McCartney'),
]
Here, ParentalKey is the replacement for Django's ForeignKey. Similarly, they have ParentalManyToManyField to replace Django's ManyToManyField.