In my application I am adding a simple message service that allows a user to send out a message to a subset of other users on the system:
from django.db import models
from django.contrib.auth.models import User
class Message(models.Model):
timestamp = models.DateTimeField()
sender = models.ForeignKey(User)
recipients = models.ManyToManyField(User)
text = models.CharField(max_length=1000)
def __unicode__(self):
return '%s %s: %s' (self.sender.first_name,self.sender.last_name,self.timestamp)
class Meta:
ordering = ('timestamp')
However, I would like to record if each user has read the message, so would need to add a boolean field to the table holding the many-to-many relationship.
Should I do this by explicitly adding another model and using ForeignKey() only, or is there a more 'django' way of doing this?
Thanks
Never mind, my googling power were weak, just found the right place in the documentation:
http://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-on-many-to-many-relationships
Related
let's suppose i have two models like below:
class Client(models.Model):
login = models.CharField(max_length=100)
password = models.CharField(max_length=100)
class Users(models.Model):
user_login = models.CharField(max_length=100)
user_pass = models.CharField(max_length=100)
One model [Users] is filled with data, second [Client] is empty. First i can populate Client based on Users. Now all Django data changes will by held only on Client model.
Question:
How to dynamically connect this two models fields? For example if some data is changed on model Client then according data will by changed also on Users model.
Solution suggestion:
I can update or populate Client data and simultaneously update or populate Users data. Is there another solution to do this?
if login is unique then no need to maintain foreign key relations, You can override the save() methods in both models else You have to maintain the foreign key relation and override the save() methods.
With help of this post i manage to link two models with below code:
class Client(models.Model):
login = models.CharField(max_length=100)
password = models.CharField(max_length=100)
# save previous instance
def __init__(self, *args, **kwargs):
super(Invoice, self).__init__(*args, **kwargs)
self.original_login = self.login
# override save method to update another model fields
def save(self, *args, **kwargs):
# import in place to avoid circular imports
from app.models import Users
if self.login != self.original_login:
Users.objects.filter(id=self.id).update(user_login=self.login)
# save changed data on Client model
super(Client, self).save(*args, **kwargs)
The same method goes to the Users model.
Note that this two model are in different apps.
I'm new to Pinax and Django. I'm trying to extend the Pinax Profile model by having a OneToOneField that pulls from another application I plugged in (in this case, django-swingtime : http://code.google.com/p/django-swingtime/). I've got all of my models to show up in the django admin interface, but I cannot add new Users (which I want to do in the process of adding new Profiles). I get the following error:
IntegrityError at /admin/auth/user/add/
profiles_profile.event_type_id may not be NULL
Request Method: POST
Request URL: http://localhost:8000/admin/auth/user/add/
Django Version: 1.3.1
Exception Type: IntegrityError
Exception Value:
profiles_profile.event_type_id may not be NULL
My Pinax version is 0.9a2. EventType is a model from django-swingtime. I get this error when I'm trying to add a User from anywhere within the Django admin.
Here's the my Profiles/models.py (changed lines have comments next to them)
from django.db import models
from django.utils.translation import ugettext_lazy as _
from idios.models import ProfileBase
from swingtime.models import EventType #ADDED HERE
class Profile(ProfileBase):
name = models.CharField(_("name"), max_length=50, null=True, blank=True)
about = models.TextField(_("about"), null=True, blank=True)
location = models.CharField(_("location"), max_length=40, null=True, blank=True)
website = models.URLField(_("website"), null=True, blank=True, verify_exists=False)
event_type = models.OneToOneField(EventType) #ADDED HERE
def __unicode__(self):
return "Name: %s -- %s" % (self.name, self.about) #ADDED HERE
Perhaps if someone could explain the relationship between accounts, profiles, and users and what files are OK to edit and which ones are inadvisable to edit (for instance, I don't think I want to be changing anything around in my Pinax site packages...), I can make some progress. Also, I assume this idios plugin is involved in the process, but the link to documentation I've found will load (http://oss.eldarion.com/idios/docs/0.1/).
Thank you!
I've solved my error, though I'm interested in other answers and additional information since some of this is speculation/still unclear to me. I think the error stems from Pinax accounts automatically creating a "blank" idios profile for every new user created (speculation). Since I had said every profile must have a OneToOne foreign field associated with it and had not allowed for this OneToOne field to be null, there was a problem.
This question describes some of the differences between the idios profile app, Pinax account and the standard django User accounts:
Difference between pinax.apps.accounts, idios profiles, and django.auth.User
What I did to solve this problem was using the Django's signalling capabilities to make sure that as soon as a Profile is generated, so is an instance of the foreign field. This is described here:
https://docs.djangoproject.com/en/1.3/topics/signals/
Make sure to read the bit about double signalling, since this has caused trouble for some other people:
https://docs.djangoproject.com/en/1.3/topics/signals/#preventing-duplicate-signals
The final modification to my code that got rid of the error was this. Note that besides adding signalling I also explicitly said that the OnetoOneField was allowed to be null.
from django.db import models
from django.utils.translation import ugettext_lazy as _
from idios.models import ProfileBase
from swingtime.models import EventType
#for signals
from django.db.models.signals import post_save
from django.dispatch import receiver
class Profile(ProfileBase):
name = models.CharField(_("name"), max_length=50, null=True, blank=True)
about = models.TextField(_("about"), null=True, blank=True)
event_type = models.OneToOneField(EventType, null=True)
def __unicode__(self):
return "Name: %s -- %s" % (self.name, self.about)
def create_User_EventType(sender, instance, created, **kwargs):
print "checking creation of profile"
if created:
print "User event type is being created"
event_label = "%s_hours" % (instance.name)
print "the event label is" + event_label
EventType.objects.create(abbr=instance.name,label=event_label)
post_save.connect(create_User_EventType,sender=Profile,dispatch_uid="event_post_save_for_profile")
Hi I have a lot of users in my system who are classified into different types. I want to store the address details of all those users. For instance the user could be a student, a school or a franchisee. All the users here could have an address information associated with them.
from django.db import models
from django.contrib.auth.Models import User
class Address(models.Model):
user = models.OneToOneField(User)
address = models.TextField()
class Student(models.Model):
user_id = models.ForeignKey(User)
address = models.ForeignKey(Address)
class School(models.Model):
user_id = models.ForeignKey(User)
address = models.ForeignKey(Address)
contact_person_name = models.CharField(max_length=50)
In this scenario there are 2 references to the User model - one through user_id and another through address.user though they should be referring to the same instance. Is it a bad practice to have duplicate references?
I thought of leaving out the 'user' foreignkey in Address, but I think that the address can't exist without a user. How to better model this?
As you already mentioned in question duplication of same field in
a model is not a good Idea.
If these are your actual models, I would suggest you using abstract
models:
from django.db import models
from django.contrib.auth.Models import User
class Profile(models.Model):
user = models.OneToOneField(User, related_name="%(app_label)s_%(class)s_related")
address = models.TextField()
class Meta:
abstract = True
class Student(Profile):
pass
class School(Profile):
contact_person_name = models.CharField(max_length=50)
This will generate two tables: students, schools with fields
user, address and user, address, contact_person_name
respectively.
I seem to have a problem after creating an unmanaged model (syncdb):
class Client_jobs(models.Model):
job_id = models.IntegerField(primary_key=True)
status = models.IntegerField()
class Meta:
db_table = 'client_jobs'
managed=False
in one of my def views, it calls the database view(Client_jobs)
def listjobs(request):
# if user is authenticated
if request.user.is_authenticated():
jobsArr = Client_jobs.objects.get.all()
The page returned me an error of
(1146, "Table 'table1.client_jobs' doesn't exist")
I know I'm missing something but I can't figure out. How does django detect this unmanaged model? Thank you.
as I know the db_table option will get precedence over the existing convention of app name_model name. If you set it explicitly you will have to prefix the application name yourself.
try client_jobs.client_jobs
I am trying to build an example app in Google App Engine using django-nonrel. and am having problems implementing ListField attribute into a model.
I have created an app test_model and have included it as an installed app in my settings. The model.py is:
from django.db import models
from djangotoolbox import *
from dbindexer import *
# Create your models here.
class Example(models.Model):
some_choices = models.ListField('Choice_examples')
notes = models.CharField(max_length='20')
updated_at = models.DateTimeField(auto_now=True)
def __unicode__(self):
return u'%s' % (self.notes)
class Choice_examples(models.Model):
name = models.CharField(max_length='30')
def __unicode__(self):
return u'%s' % (self.name)
The above example gives me:
AttributeError:'module' object has no attribute 'Model'
If I comment out the djangotoolbox import, I get the following :
AttributeError: 'module' object has no attribute 'ListField'
What am I doing wrong here? I can't seem to find any documention as to how to go about using ListField in django-nonrel. Is that because it is supposed to really obvious?
Your imports are smashing each other:
from django.db import models
from djangotoolbox import *
The second import will replace the django.db models with djangotoolbox' empty models module. Using from X import * is a terrible idea in general in Python and produces confusing results like these.
If you're looking to use ListField from djangotoolbox, use:
from djangotoolbox import fields
and refer to the ListField class as fields.ListField.
OK, here is what I did to be able to use ListFields. MyClass the equivalent to your Example class and AnotherClass is the same as your Choice_examples. What I describe will allow you to use ListFields in the admin interface and your self implemented views.
I'll start from the beginning
This is what what my model looks like
class MyClass(models.Model):
field = ListField(models.ForeignKey(AnotherClass))
I wanted to be able to use the admin interface to create/edit instances of this model using a multiple select widget for the list field. Therefore, I created some custom classes as follows
class ModelListField(ListField):
def formfield(self, **kwargs):
return FormListField(**kwargs)
class ListFieldWidget(SelectMultiple):
pass
class FormListField(MultipleChoiceField):
"""
This is a custom form field that can display a ModelListField as a Multiple Select GUI element.
"""
widget = ListFieldWidget
def clean(self, value):
#TODO: clean your data in whatever way is correct in your case and return cleaned data instead of just the value
return value
These classes allow the listfield to be used in the admin. Then I created a form to use in the admin site
class MyClassForm(ModelForm):
def __init__(self, *args, **kwargs):
super(MyClasstForm,self).__init__(*args, **kwargs)
self.fields['field'].widget.choices = [(i.pk, i) for i in AnotherClass.objects.all()]
if self.instance.pk:
self.fields['field'].initial = self.instance.field
class Meta:
model = MyClass
After having done this I created a admin model and registered it with the admin site
class MyClassAdmin(admin.ModelAdmin):
form = MyClassForm
def __init__(self, model, admin_site):
super(MyClassAdmin,self).__init__(model, admin_site)
admin.site.register(MyClass, MyClassAdmin)
This is now working in my code. Keep in mind that this approach might not at all be well suited for google_appengine as I am not very adept at how it works and it might create inefficient queries an such.
I don't know, but try with:
class Choice_examples(models.Model):
name = models.CharField(max_length='30')
def __unicode__(self):
return u'%s' % (self.name)
class Example(models.Model):
some_choices = models.ListField(Choice_examples)
notes = models.CharField(max_length='20')
updated_at = models.DateTimeField(auto_now=True)
def __unicode__(self):
return u'%s' % (self.notes)
Looks like the answer is that you cannot pass an object into fields.ListField.
I have ditched trying to work with ListField as documentation is limited and my coding skills aren't at a level for me to work it out.
Anyone else coming across a similar problem, you should consider create a new model to map the ManyToMany relationships. And if the admin view is important, you should look into the following to display the ManyToMany table inline with any given admin view:
http://docs.djangoproject.com/en/1.2/ref/contrib/admin/#s-working-with-many-to-many-models