I'm django learner and i have problem with django relationship concept.
I have written two models that have relations with single source model (UserProfile).but one of them does not work properly.The Message class work fine with it's two fields (sender,receiver),but the other class(Class) lead to
programing error:relation "CEA_class" already exists
where CEA is my app name.I really prefer to have two different field for the class and don't join them as single field.What I'm suppose to do with it?
class Message ---->that work fine
class Message(models.Model):
sender = models.ForeignKey(UserProfile,blank=False,related_name="sender")
receiver = models.ForeignKey(UserProfile,blank=False,related_name="receiver")
content = models.CharField(max_length=200)
priority = models.BigIntegerField(choices=PRIORITY_LIST,default=1)
class Class ---->that lead to error
class Class(models.Model):
subject = models.CharField(max_length=20)
time = models.CharField(max_length=20)
day = models.CharField(max_length=20)
location = models.CharField(max_length=20)
students = models.ManyToManyField(UserProfile,blank=True,related_name="students")
master = models.ForeignKey(UserProfile,blank=True,related_name="master")
Here is my whole UserProfile class
class UserProfile(models.Model):
user=models.OneToOneField(User,
related_name='UserProfile',on_delete=models.CASCADE)
field=models.CharField(max_length=20,default="ce")
userPhoto=models.ImageField(upload_to='documents/',blank=True)
Type=models.BigIntegerField(choices=USER_TYPE,default=2)
gender=models.BigIntegerField(choices=GENDER_TYPE,default=1)
def __str__(self):
return self.user.username
#The decorator can also takes extra arguments which are passed onto the
signal
#receiver(post_save,sender=User)
def create_or_update_UserProfile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
instance.UserProfile.save()
I have an error in my admin page as below:
.
ProgrammingError at /admin/CEA/class/
column CEA_class.master_id does not exist LINE 1: ...time",
"CEA_class"."day", "CEA_class"."location", "CEA_class...
I solved this a while ago and found some references including in the Django doc, but I'm actually still not quite sure why this is needed as the underlying SQL structure doesn't (as far as I can tell in looking at my own database) show the variance in related_name - it appears to be an internal Django issue rather than an actual SQL issue. In any case, when you have more than one field related to the same other model within a table then all except one have to have something referencing the class in order to get Django to keep things straight. It is often cleanest to add class to ALL the related_names within a model that has the problem for consistency, though I have checked my own code and sometimes I do that, sometimes I don't:
students = models.ManyToManyField(UserProfile,blank=True,related_name="%(class)s_students")
master = models.ForeignKey(UserProfile,blank=True,related_name="%(class)s_master")
After all i came to this conclusion that the best way for deleting the Annoying irrelevant data that cause the problems is to temporary rename the model and migrate and then rename it to it's first name.By this way django itself take care of deleting relations and every data in database that causes your problem.
With all these interpretations,all of the suggested answers was helpful but i think the simple is better,why not. :))
Related
Is it possible without related name (related_name="+") to prefetch objects on the target instance? Sure I know it's not a problem with the related name, but I'm not really sure if it's possible without it.
Here is the example code:
from django.db import models
class Parent(models.Model):
name = models.CharField(max_length=50)
class Child(models.Model):
parent = models.ForeignKey(to=Parent, related_name="+", on_delete=models.CASCADE)
name = models.CharField(max_length=50)
Parent.objects.all().prefetch_related('child_set')
Maybe it's possible using the Prefetch(lookup, queryset=None, to_attr=None) object, because it takes the queryset in the argument list?
Looked through the code a bit and found this line:
rel_obj_descriptor = getattr(instance.__class__, through_attr, None)
Here instance is the model instance, and through_attr is the field name of related instance to be fetched. This line basically tries to get a related descriptor to perform the prefetch query. In your case rel_obj_descriptor would contain None.
To answer your question no it is not possible at least for a Foreign Key, there may be some hack for Many to Many relationships as Django appears to use some internal descriptors for them.
I would advice you to simply not set related_name="+" since you want to use the backwards relation here. You say "It's because of separation of concerns between multiple apps" but that does not make much sense. Don't we set a foreign key to the user model for various other models anyway and still use the related name? Does the point of separation of concerns arise there(the user model is in a separate app)?
try
parent = Parent.objects.get(id=pk)
parent.child_set.all()
I don't know if having related_name = '+' prevents this situation, but if you never define related_name, you can definitely use this method.
Right now, I have an abstract model with several models that inherits its fields. But I have discovered the power of Proxy models, and I want to implement them to my app. This is a picture from now:
class BaseModel(models.Model):
field_1 = models.CharField(max_length=10)
field_2 = models.CharField(max_length=10)
field_3 = models.CharField(max_length=10)
class Meta:
abstract = True
class Model1(BaseModel):
pass
def __unicode__(self):
return self.field_1
class Model2(BaseModel):
pass
def __unicode__(self):
return self.field_1
And this is what I want:
class BaseModel(models.Model):
field_1 = models.CharField(max_length=10)
field_2 = models.CharField(max_length=10)
field_3 = models.CharField(max_length=10)
class Model1(BaseModel):
pass
class Meta:
proxy = True
def __unicode__(self):
return self.field_1
class Model2(BaseModel):
pass
class Meta:
proxy = True
def __unicode__(self):
return self.field_1
The problem is when I remove the "abstract = True" sentence. When I try to migrate, this is the warning:
You are trying to add a non-nullable field 'basemodel_ptr' to Model1 without a default; we can't do that (the database needs something to populate existing rows).
Ok, got it. I read "ptr" is a pointer to the parent model, which is BaseModel, but I don't have any BaseModel, and I cannot get it until I migrate. How can I fix this??
The migrations for this are not trivial.
Currently, your database has two tables:
yourapp_model1
yourapp_model2
Both have the same columns but they use different sequences meaning that their primary keys clash: Both of the tables will start counting their IDs (aka PKs) from 1 onwards. There is a very good chance that there is an instance of Model1 with pk=1 as well as an instance of Model2 with pk=1 and they are not the same.
This is the point of having an abstract model and concrete implementations: share Django code (business logic) while separating the data in the DB. For example, because it is semantically different (different types).
The point of proxy models is the exact opposite: while the data is located in one table in the DB, the proxy models allow you to implement different behaviour but based on the same DB data.
If you are now migrating from abstract models to proxy models it means that what you once considered different types will now become the same types (from a database point of view). As mentioned at the beginning, you will have to move the data from several tables into one and regenerate the IDs for at least part of it. Meaning also, that part of the resources that are currently using these URLs will change/cease to exist/point to a different resource.
Unless you can start from scratch (no live data that you have to support) you should really appreciate the magnitude of this change.
Should you not have the need to support live data:
drop the database
recreate the database
remove all migration files
recreate all migration files from scratch
call migrate
Data migration of live data:
Note that there are other ways to do this. Search for "Django data migration".
create the new Model structure with new names (no collisions)
makemigrations which will now pick up the new model structure and create new and empty tables in database leaving the old tables and their data untouched
create a management command that reads in the old model instances and copies them into the new tables
once this command has been run on production you can deprecate the old models and remove them while making sure that everything that was depending on them is now using the new tables
Up until recently, a project I'm working used one mega UserProfile to handle all profile data for two different types of users. Naturally this was messy, and it was about time to refactor it.
In my attempt to refactor the model, I split the model into Requester and Funder and created an abstract UserProfile model which both subclass:
class UserProfile(models.Model):
class Meta:
abstract = True
user = models.OneToOneField(User)
def __unicode__(self):
return unicode(self.user)
class Requester(UserProfile):
def requested(self, event):
"""Check if a user requested an event."""
return self == event.requester
class Funder(UserProfile):
osa_email = models.EmailField(null=True) # The e-mail of the contact in OSA
mission_statement = models.TextField(max_length=256)
And in my settings.py file, I adjusted the AUTH_PROFILE_MODULE.
AUTH_PROFILE_MODULE = "app.UserProfile"
The problem is, when hitting a page that uses "User.get_profile()" it breaks, reporting:
Unable to load the profile model, check AUTH_PROFILE_MODULE in your project settings
I'm not quite sure what's going on here. According to the docs, everything looks right.
Can some explain why this fails? (There are a bunch of alternative solutions I've come across, but I'd much prefer to fix this if possible than adopt some hack.)
What you are trying to do it not possible. AUTH_PROFILE_MODULE is expecting a concrete model, not an abstract one. Concrete means it has a table and can create instances. An abstract model can only be subclassed.
A logic reason why this not possible it that django has no one of knowing which model instance to return for your user. A Requester? A Funder? Simply being an abstract reference gives django no hints. One approach might be to look into the contenttypes framework and maybe come up with a generic UserProfile model containing a reference to the proper sub-profile type. You could then remove the abstract=True from your UserProfile, and create a generic relation to the specific Profile model. AUTH_PROFILE_MODULE would then simply reference that single UserProfile, but its instances can then use the .content_object to get the specific subobject.
There are many ways I'm sure you could address this problem, but I am just commenting on the reason why this specific approach does not work.
I am gradually replacing a legacy database front end with a django based system. All models are Managed = False, to preserve the original db structure.
However I have struck a problem where a field in a table is computed. The field is defined in (pseudo) sql as full_name = fname|| ||lname.
I can define the full_name field as a charfield; and I can read it no problems, however any attempt to update the record results in an update error on that field.
I can use a #property; but that replicates the functionality in django, rather than displaying the results from the db itself. Using this approach will cause problems with more complex fields (in tables I am yet to get to) that are defined with UDFs.
What is really needed is a 'read_only' or 'computed' attribute on the model itself; what is the best way to achieve this?
Do you just want to define a method in your class? Something like:
def Person(models.Model):
fname=models.CharField(...)
lname=models.CharField(...)
def fullname(self):
return self.fname+" "+self.lname
(not exactly sure what Managed=False means...)
if you are trying to make calculation on a database models and pass the value of a model field to another model field of the same class model, using a defined function then this solution might help you. for example lets assume you have an investment company and you give 20% per month for the capital each user invested, you would want want to pass value from capital model to a function that calculates the percentage interest, and then you will pass that function into another field monthly_payment and get saved in the database.
1) pip install django-computed-property
2) add 'computed_property' to your installed apps in project settings.
3) in your models.py, import computed_property then
class Investment(models.Model):
name = models.CharField(max_length=200)
capital = models.FloatField(null=False)
percentage = models.CharField(max_length=5)
duration = models.CharField(max_length=10, default="1 months")
monthly_payment = computed_property.ComputedFloatField( compute_from='monthly_percentage', null=False, blank=False)
then your function to perform the calculation will go thus
#property
def monthly_percentage(self):
return (20 / 100) * self.capital
Note: what i discovered was if you use the inbuilt django fields be it FloatFiled or IntegerField, this function won't read the amount you are passing in to get your 20% calculations.i hope this works for you as i stated all as they worked for me,cheers.
I posted this question on the django-users list, but haven't had a reply there yet.
I have models that look something like this:
class ProductGroup(models.Model):
name = models.CharField(max_length=10, primary_key=True)
def __unicode__(self): return self.name
class ProductRun(models.Model):
date = models.DateField(primary_key=True)
def __unicode__(self): return self.date.isoformat()
class CatalogItem(models.Model):
cid = models.CharField(max_length=25, primary_key=True)
group = models.ForeignKey(ProductGroup)
run = models.ForeignKey(ProductRun)
pnumber = models.IntegerField()
def __unicode__(self): return self.cid
class Meta:
unique_together = ('group', 'run', 'pnumber')
class Transaction(models.Model):
timestamp = models.DateTimeField()
user = models.ForeignKey(User)
item = models.ForeignKey(CatalogItem)
quantity = models.IntegerField()
price = models.FloatField()
Let's say there are about 10 ProductGroups and 10-20 relevant
ProductRuns at any given time. Each group has 20-200 distinct
product numbers (pnumber), so there are at least a few thousand
CatalogItems.
I am working on formsets for the Transaction model. Instead of a
single select menu with the several thousand CatalogItems for the
ForeignKey field, I want to substitute three drop-down menus, for
group, run, and pnumber, which uniquely identify the CatalogItem.
I'd also like to limit the choices in the second two drop-downs to
those runs and pnumbers which are available for the currently
selected product group (I can update them via AJAX if the user
changes the product group, but it's important that the initial page
load as described without relying on AJAX).
What's the best way to do this?
As a point of departure, here's what I've tried/considered so far:
My first approach was to exclude the item foreign key field from the
form, add the substitute dropdowns by overriding the add_fields
method of the formset, and then extract the data and populate the
fields manually on the model instances before saving them. It's
straightforward and pretty simple, but it's not very reusable and I
don't think it is the right way to do this.
My second approach was to create a new field which inherits both
MultiValueField and ModelChoiceField, and a corresponding
MultiWidget subclass. This seems like the right approach. As
Malcolm Tredinnick put it in
a django-users discussion,
"the 'smarts' of a field lie in the Field class."
The problem I'm having is when/where to fetch the lists of choices
from the db. The code I have now does it in the Field's __init__,
but that means I have to know which ProductGroup I'm dealing with
before I can even define the Form class, since I have to instantiate the
Field when I define the form. So I have a factory
function which I call at the last minute from my view--after I know
what CatalogItems I have and which product group they're in--to
create form/formset classes and instantiate them. It works, but I
wonder if there's a better way. After all, the field should be
able to determine the correct choices much later on, once it knows
its current value.
Another problem is that my implementation limits the entire formset
to transactions relating to (CatalogItems from) a single
ProductGroup.
A third possibility I'm entertaining is to put it all in the Widget
class. Once I have the related model instance, or the cid, or
whatever the widget is given, I can get the ProductGroup and
construct the drop-downs. This would solve the issues with my
second approach, but doesn't seem like the right approach.
One way of setting field choices of a form in a formset is in the form's __init__ method by overwriting the self.fields['field_name'].choices, but since a more dynamic approach is desired, here is what works in a view:
from django.forms.models import modelformset_factory
user_choices = [(1, 'something'), (2, 'something_else')] # some basic choices
PurchaserChoiceFormSet = modelformset_factory(PurchaserChoice, form=PurchaserChoiceForm, extra=5, max_num=5)
my_formset = PurchaserChoiceFormSet(self.request.POST or None, queryset=worksheet_choices)
# and now for the magical for loop
for choice_form in my_formset:
choice_form.fields['model'].choices = user_choices
I wasn't able to find the answer for this but tried it out and it works in Django 1.6.5. I figured it out since formsets and for loops seem to go so well together :)
I ended up sticking with the second approach, but I'm convinced now that it was the Short Way That Was Very Long. I had to dig around a bit in the ModelForm and FormField innards, and IMO the complexity outweighs the minimal benefits.
What I wrote in the question about the first approach, "It's straightforward and pretty simple," should have been the tip-off.