Django: Entering instances of classes with empty collections - python

I have a Django application with following class:
class Opinion(models.Model):
id = models.AutoField(primary_key=True)
contents = models.CharField(max_length=256)
source = models.CharField(max_length=256)
proArguments = models.ManyToManyField('self', verbose_name="Pro arguments", related_name='proargs', null='true', blank='true')
contraArguments = models.ManyToManyField('self', verbose_name="Contra arguments", related_name='contraarg', null='true', blank='true')
def __unicode__(self):
return self.contents
When I try to create a new instance of this class in the admin, the newly created opinion has one proArgument and one contraArgument, even though I didn't enter them.
What can I do in order for proargs and contraarg to be empty, when I don't enter them?

The multiple select widget for both many to many fields contains all possible Opinions. In your screenshot, there are no Opinions selected for these fields. They are not selected until you click on one or more opinions and save.
You might find the filter_horizontal and filter_vertical model admin options helpful. They make it clearer which objects are selected.

Related

django admin, displaying all instances of a model1 associated with model2 on model2's change page?

Consider these two models Keyword and Statement (model1 and model2 respectively):
#python_2_unicode_compatible
class Keyword(models.Model):
word = models.CharField(max_length=200)
statement = models.ManyToManyField(Statement)
def __str__(self):
return self.word
#python_2_unicode_compatible
class Statement(models.Model):
statement_id = models.CharField(max_length=200)
title = models.CharField(max_length=200)
issue_date = models.DateField("Issue-Date")
author = models.ForeignKey(Person)
released_by = models.ForeignKey(Organization)
kicpairs = models.ManyToManyField('KeywordInContext')
So on the admin site right now, the only way one would be able to determine what keywords are associated with each statement is that they have to go check the Keyword model in admin, and check each Keyword's display page and scroll through the menu.
At least with regards to the admin site, it's important for someone to be able to see a Statement model's display with all of its associated Keywords visible, and for users to be able to choose additional Keywords within the database (or make new ones). I also hope to be able to have a Statement's keywords modifiable on the admin page via the filter_horizontal widget, since that seems to be the most user friendly.
But I'm having trouble just starting with that. I'm not sure what I need to use or how.

Delete m2m through field from admin panel

I searched and could not find a way to do this. Here's my situation:
I have 3 classes:
Publication
Person
AuthorOrder
The last is a through class that allows me to specify the author order for a publication, as this does not normally seem possible to do.
Initially, I made Author a mandatory field (blank=False) for Publication and added a placeholder Person object to add Publications to that don't have a proper author. However, a better solution seems to be to just handle missing authors in Views appropriately. Now, I've changed the field to be optional, but I cannot seem to set the authors to empty via the admin panel. It gives me a "This field is required." error. My guess is that this is because the Person is required of the through class, but setting the Person to null/empty in the admin panel does not set the through object to null/empty.
I found a workaround. One can delete the placeholder Person object. This unsets the through class from the Publications without deleting them via cascade as they are no longer mandatory. However, this is not always a good workaround, so I hope there's a better method.
models.py
There is a lot of code, I reproduce only the minimal necessary:
#Publication
class Publication(models.Model):
authors = models.ManyToManyField(Person, blank=True, related_name="author_of", through='AuthorOrder')
#Person
class Person(models.Model):
# mandatory
firstname = models.CharField(max_length=200)
# AuthorOrder
class AuthorOrder(models.Model):
publication = models.ForeignKey(Publication)
author = models.ForeignKey(Person)
admin.py
# AuthorInline
class AuthorInline(admin.StackedInline):
model = AuthorOrder
extra = 3
# Publication
class PublicationAdmin(admin.ModelAdmin):
list_display = ("title", 'issue', "keywords")
search_fields = ['title', "keywords"]
list_filter = ['issue']
# author list via Inline
inlines = [AuthorInline]
admin.site.register(Publication, PublicationAdmin)
It's simple. To the very right of the "Author order: AuthorOrder object" line, there is a small "Delete" box. Check it and save. It's small and somewhat oddly placed, so easily gets missed.

Django databases with multiple relations and ForeignKeys

I have multiple databases with different relations and I'm unable to figure out how to properly structure things to avoid problems in Django Admin.
Here is the design I want:
Category
-> 'name' (CharField)
Movie
-> Multiple CharFields
CategoryLink
-> 'category' (ForeignKey -> Category)
-> 'movie' (ForeignKey -> Movie)
-> 'prefix' (ForeignKey -> Prefix) - Blank, Null
-> 'number' (DecimalField)
Prefix
-> 'category' (ForeignKey -> Category)
-> 'prefix' (CharField)
I want to achieve is a structure where:
Each Category can have multiple CategoryLinks to Movies
Movies can exist within any number of Categories any number of times.
CategoryLinks can have a Prefix, but doesn't have to have one.
Prefixes are limited to specific Categories
Editing a Prefix for a specific Category has no effect on a prefix of the same name for a differ Category
Categories can have multiple or zero Prefixes
Prefixes can only be used by a CategoryLink if the Prefix.category == CategoryLink.category
Unrelated Prefixes are hidden from Categories
My main issue is that when I try to limit the choices of Prefixes to only display choices relevant to the current Category I run into a wall. I can do it fine when editing a CategoryLink, but not when adding a new one.
If I try to limit the choices in the Admin Panel with something like this:
#admin.py
# ....
def __init__(self, *args, **kwargs):
super(PrefixForm, self).__init__(*args, **kwargs)
Prefix.objects.filter(category_id=self.instance.category.id)
It works fine while editing, but it throws an error whenever I'm in a form which has the ability to add new entries. Since the new entries doesn't have a defined category.id by virtue (I assume) of not existing yet Django throw an "RelatedObjectDoesNotExist" exception at me.
If I can get it to work while editing an existing Category that would be fine. I don't need to be able to create new CategoryLinks without having a Category already, but when I try I get the same error since I'm using a TabularInline class to include CategoryLinks into Category.
I'm willing to completely restructure everything to get this to work, as you can probably tell I'm new to Django so it's possible I'm thinking about this all wrong.
I asked a similar question last week that I thought I had figured out on my own, but it turned out I simply pushed the problem a step rather than solve it.
Is there a better way to structure my models or is there something I can do within admin.py to properly filter prefixes to categories? Let me know if you want to see all my code, it seemed a bit too much to post here.
I could "solve" this issue by turning CategoryLink.prefix into a CharField, but it would be so much cooler if I could have a separate model for Prefixes.
Here is my full Model.py (minus some irrelevant __unicode__ stuff)
from django.db import models
class Category(models.Model):
class Meta:
verbose_name_plural = "Categories"
name = models.CharField(max_length=255, unique=True)
def category_link_count(self):
return len(CategoryLink.objects.filter(category_id=self.id))
category_link_count.short_description = 'Movies in Category'
class Movie(models.Model):
title = models.CharField(verbose_name='Movie Title', max_length=300)
year = models.DecimalField(verbose_name='Year of Release',
max_digits=4, decimal_places=0)
class CategoryLink(models.Model):
class Meta:
verbose_name = "Category Link"
verbose_name_plural = "Category Links"
category = models.ForeignKey(Category)
movie = models.ForeignKey(Movie)
prefix = models.ForeignKey('Prefix', blank=True, null=True)
number = models.DecimalField(verbose_name='Movie Number', max_digits=2,
blank=True, null=True, decimal_places=0)
class Prefix(models.Model):
category = models.ForeignKey(Category)
prefix = models.CharField(verbose_name='Category Prefix', max_length=255)
class Meta:
verbose_name = "Prefix"
verbose_name_plural = "Prefixes"
ordering = ['-category']
My suggestion is to have defaults for fields that have relations with other models, that way you can create a a Category and have an arbitrary Prefix. However, I think you have structured your models inappropriately.
Category has a ManyToManyField to Prefix which has a FK to Category. You don't need the FK. This is just one, but you can really simplify your organization. I don't know enough about what you want to accomplish.

Can't bind many to many field correctly

I have 2 models:
class Tag(models.Model):
"""
model for tag
"""
# name of tag
name = models.CharField(max_length=30, verbose_name="tag name", unique=True)
def __str__(self):
return self.name
class Note(models.Model):
"""
model for note
"""
# date of publication note
publication_date = models.DateField("Publication date", auto_now_add=True)
# date of last change
date_last_change = models.DateField("Last changed", auto_now=True)
# note title
title = models.CharField(max_length=200, verbose_name="Note title")
# main text of note
main_text = models.TextField("Note text")
# tags
tags = models.ManyToManyField(Tag, related_name='Tags')
def __str__(self):
return self.title
As you see, one note has many tags, and one tag is related to many notes. But when I started to fill data in admin panel, I noticed that when I add a tag in note it automatically binds to all notes. Even if I add tag with Tag menu in admin panel it also binds to all notes.
I already tried manually adding model like NoteTag with foreign keys to Note and Tag but have the same issue. I still new in django and little bit confused by this situation.
Are you sure about this? Is it possible you've get confused by default django ManyToManyField widget showing all related records?
Try to check it with shell this way:
note = Note.objects.get(id=1)
note.tags.all()
will print all note tags.
And you can tweak widgets with third-party apps (https://pypi.python.org/pypi/django-widget-tweaks/1.3) But i guess this is not so simple :)

Django one-to-many, add fields dynamically in Admin

I have the following code:
class Item(models.Model):
name = models.CharField(max_length=100)
keywords = models.CharField(max_length=255)
type = models.ForeignKey(Type)
class Meta:
abstract = True
class Variant(models.Model):
test_field = models.CharField(max_length=255)
class Product(Item):
price = models.DecimalField(decimal_places=2, max_digits=8,null=True, blank=True)
brand = models.ForeignKey(Brand)
variant = models.ForeignKey(Variant)
def get_fields(self):
return [(field.name, field.value_to_string(self)) for field in Product._meta.fields]
def __unicode__(self):
return self.name
Im using Grappelli.
I want my Product to have multiple Variations. Should I use a manytomanyfield?
I want to be able to add Variants to my Product directly in the Admin. Now I get an empty dropwdown with no variants(because they doesnt exists).
I thought Django did this automatically when u specified a Foreign Key?
How can I get the Variant fields to display directly on my Product page in edit?
I've read someting about inline fields in Admin?
Well, it's the other way around :)
1/ Place the foreign key field in your Variant, not in your Product (what you describe is actually a OneToMany relationship).
2/ Link the Variant to your Product in the relative ProductAdmin in admin.py as an inline (i.e VariantInline).
See the docs for further informations : https://docs.djangoproject.com/en/1.6/ref/contrib/admin/#inlinemodeladmin-objects
Hope this helps !
Regards,

Categories