many to many field omitted in database table when running syncdn - django

I have a field with M2M relationship.when running syncdb,the field with M2M field does not form on the database.
here is the model
class Eventgroups(models.Model):
event=models.ManyToManyField(Event)
group_name=models.CharField(max_length=100)
def __unicode__(self):
return "%s, %s" \
% (self.group_name, self.event)
class Meta:
db_table= 'eventgroup'
verbose_name_plural='eventgroups'
events field is not created on database
I would appreciate an insight to this problem please
Regards,
Joshua

Everything is ok. You just don't understand how ManyToMany is realized on the SQL level. Simply speaking, this
class Foo(models.Model):
#...
class Bar(models.Model):
foo = models.ManyToManyField(Foo)
is technically the same as this:
class Foo(models.Model):
#...
class Bar(models.Model):
#...
class BarFoo(models.Model):
foo = models.ForeignKey(Foo)
bar = models.ForeignKey(Bar)
And if you'll check your database - you will find a table called EventgroupsEvent or something like that which contains the actual fields. It's just the ORM that lets you connect the models directly. Please read my answer here for a detailed explanation on how ManyToMany works in the background

It wont create a field named event instead, it will create a new table Eventgroups_event

Related

Return all model results, but filter out the ManyToManyFields

I'm trying to filter out the results from a model so all fields return, but I can filter just one ManyToManyField in the model. I'd only like it to filter out on the page, and not in the Admin.
I've found some great information about ManyToMany filtering but, for some reason, nothing that helps in this particular case. So I guess I'm either doing it very wrong, or I'm missing an important search term. I've tried filtering in models, in views, and in the template.
Here's a minimal example to help explain:
# models.py
class Foo(models.Model):
name = models.CharField(unique=True, max_length=255)
bars = models.ManyToManyField(Bar)
class Bar(models.Model):
thing = models.CharField(max_length=12)
is_public = models.BooleanField(default=False)
# views.py
class FooDetail(DetailView):
def get_queryset(self):
# Would I filter in here?
return super(FooDetail, self).get_queryset()
I would like the Foo model to return all foos, but for each foo only includes bars that are true for is_public
Where do I filter out the Bar results for the Foo model?
I found this question which is basically what I'm asking, but the answer is specific to that question and shows it filtered in the Serializer. So I don't understand how/where to apply that answer here where I'm not doing any serialization. (should I be?)
You can use Prefetch() objects [Django docs] and pass the queryset keyword argument to do this:
from django.db.models import Prefetch
foo_queryset = Foo.objects.prefetch_related(
Prefetch(
'bar_set',
queryset=Bar.objects.filter(is_public=True),
to_attr='public_bars'
)
)
Now you can access the related Bar instances which are public by using:
for foo in foo_queryset:
print(foo.public_bars)

Trouble overriding save method on Django model with ManyToManyField

I'm having trouble overriding the save method on a Django model to check a restriction on a many-to-many field.
Say I have the following models:
class Person(models.Model):
name = models.CharField()
class ClothingItem(models.Model):
description = models.CharField()
owner = models.ForeignKey(Person)
class Outfit(models.Model):
name = models.CharField()
owner = models.ForeignKey(Person)
clothing_items = models.ManyToManyField(ClothingItem)
I would like to put a restriction on the save method of Outfit that ensures that each ClothingItem in a given outfit has the same owner as the Outfit itself.
I.e. I'd like to write:
class Outfit(models.Model):
name = models.CharField()
owner = models.ForeignKey(Person)
clothing_items = models.ManyToManyField(ClothingItem)
def save(self, *args, **kwargs):
for ci in self.clothing_items:
if ci.owner != self.owner:
raise ValueError('You can only put your own items in an outfit!)
super(Outfit, self).save(*args, **kwargs)
but when I try that I get an error about <Outfit: SundayBest>" needs to have a value for field "outfit" before this many-to-many relationship can be used.
Any ideas what's going wrong here?
There are two issues going on here. To directly answer your question, the error basically means: You cannot refer to any m2m relationship if the original object(an instance of Outfit here) is not saved in database.
Sounds like you are trying to do the validation in save() method, which is a pretty bad practice in django. The verification process should typically happen in Form that creates Outfit objects. To override default django form, please refer to django ModelAdmin.form. To understand how to do validation on django forms, check ModelForm validation.
If you want code to refer to for m2m validation, I found a good example from SO.

How do I define the __str__ method for a foreignkey field in Django?

How do I define the str method for a foreignkey field in Django? The code below does not work,
class A(models.Model):
name = models.ForeignKey('B')
def __str__(self):
return self.name
If your model B has a name field, you could:
def __str__(self):
return self.name.name
Or you could try define the __str__ method in B model.
Table 'A' has a Foreign Key of Table 'B', You can Define like this:
class B(models.Model):
something=models.CharField(max_length=50)
class A(models.Model):
name = models.ForeignKey('B')
def __str__(self):
return self.name.something
#Gocht has the correct answer, the code at the moment is basically calling the str method of your Model B, which is presumably unset.
You can reference foreign key fields in the STR box, but unless you also set list_display on the ModelAdmin for Model A I'd not reccomend it if you need a responsive admin module.
You will end up with literally thousands of queries for each page load. Any bulk deletion task will become a vision of eggtimers..

Django InlineAdmin for ManyToMany field which doesn't have an explicitly named through

I have two models, with ManyToMany relationships:
App1:
class Foo:
fld = models.CharField(null=True, blank=True)
App2:
class Bar:
foos = models.ManyToManyField(Foo, blank=True)
Now, on the admin view of Bar, I'd like to present foos. I cannot simply list foos as a ManyToMany field, I get an error message.
So I try to do:
class BarFooInline(admin.TabularInline):
model = Bar_foos
class BarAdmin(admin.ModelAdmin):
model = Bar
inlines = [BarFooInline, ]
admin.site.register(Bar, BarAdmin)
I got the name Bar_foos by look into the Meta of Bar. Bar.foos.through yields that as a proper models.Bar_foos. But since I didn't explicitly name the through, it's not really in the models.py, so I cannot import that. What should I do?
I don't want to create a through now, because I already have a whole bunch of association information in the table, and I have a feeling that wouldn't be magically data migrated into the newly named association entity's table (https://mounirmesselmeni.github.io/2013/07/28/migrate-django-manytomany-field-to-manytomany-through-with-south/).
Also, I cannot move the ManyToMany field from App2 to App1.
class BarFooInline(admin.TabularInine):
models = Bar.foos.through
class BarAdmin(admin.ModelAdmin):
model = Bar
inlines = [BarFooInline]
exclude = ['foos']
Working with many-to-many models.

Django: list_filter and foreign key fields

Django doesn't support getting foreign key values from list_display or list_filter (e.g foo__bar). I know you can create a module method as a workaround for list_display, but how would I go about to do the same for list_filter? Thanks.
Django supports list_filter with foreign key fields
# models.py:
class Foo(models.Model):
name = models.CharField(max_length=255)
def __unicode__(self):
return self.name
class Bar(models.Model):
name = models.CharField(max_length=255)
foo = models.ForeignKey(Foo)
# admin.py:
class BarAdmin(admin.ModelAdmin):
list_filter = ('foo__name')
From documentation: Field names in list_filter can also span relations using the __ lookup
Well, the docs say that you can may use ForeignKey field types in list_filter:
http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_filter
An example:
# models.py:
class Foo(models.Model):
name = models.CharField(max_length=255)
def __unicode__(self):
return self.name
class Bar(models.Model):
name = models.CharField(max_length=255)
foo = models.ForeignKey(Foo)
# admin.py:
class BarAdmin(admin.ModelAdmin):
list_filter = ('foo')
If you want to filter by a field from the related model, there's a patch on the way to make this work (will probably be merged into 1.2 as it seems):
http://code.djangoproject.com/ticket/3400
solution from this page worked for me http://www.hoboes.com/Mimsy/hacks/fixing-django-124s-suspiciousoperation-filtering/
define
class SmarterModelAdmin(admin.ModelAdmin):
valid_lookups = ()
def lookup_allowed(self, lookup, *args, **kwargs):
if lookup.startswith(self.valid_lookups):
return True
return super(SmarterModelAdmin, self).lookup_allowed(lookup, *args, **kwargs)
then allow the lookup for certain foreign key field
class PageAdmin(SmarterModelAdmin):
valid_lookups = ('parent')
If you construct the URL for the changelist manually then Django has no problems following relationships. For example:
/admin/contact/contact/?participant__event=8
or
/admin/contact/contact/?participant__event__name__icontains=er
Both work fine (although the latter doesn't add 'distinct()' so might have duplicates but that won't usually be an issue for filters)
So you just need to add something to the page that creates the correct links. You can do this either with by overriding the changelist template or by writing a custom filterspec. There are several examples I found by Googling - particularly on Django Snippets
You can easily create custom filters since Django 1.4 by overriding django.contrib.admin.SimpleListFilter class.
More information :
Admin list_filter documentation ;
Django-1.4 release note.
I ran into the same problem and really needed a solution. I have a workaround that lets you create a filter on a FK related model property. You can even traverse more than one FK relationship. It creates a new FilterSpec subclass that subclasses the default RelatedFilterSpec used to give you a filter on a ForeignKey field.
See http://djangosnippets.org/snippets/2260/
The Haes answer works perfectly, but if the __ looks up to another ForeignKey field, you end up with a blank result. You must place another __ lookup, until it points to the real field.
In my case: list_filter = ('place__condo__name', )
my models.py:
class Condo(models.Model):
name = models.CharField(max_length=70)
...
class Place(models.Model):
condo = models.ForeignKey(Condo)
...
class Actions(models.Model):
place = models.ForeignKey(Place)
...