Can't bind many to many field correctly - python

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 :)

Related

How to auto increment a model field in django admin form by having add another on the side?

I have this model:
class BlogPost(models.Model):
author = models.CharField(max_length=64, default='Admin')
image = models.ImageField(blank=True, null=True)
title = models.CharField(max_length=255)
caption = models.CharField(max_length=500)
content = RichTextUploadingField()
# todo support for tags
tags = models.CharField(max_length=255, default='travel') #todo
date_created = models.DateField()
Now in tags field, I want to give multiple strings like #tips, #travel, etc on the same field. What I want is there should be like an add or increment tag, which when I click will show another tag field appears on the admin form and the user can adder another tag.
My backend is not on the regular HTML page. I have customized the default Django admin page for the backend using the material package. That is I cant use button tag and all.
How can I achieve this?? I have an image attached which explains better.
Image here
You can create another model called Tag and connect it to your BlogPost like this:
class Tag(models.Model):
text = models.CharField(max_length=244, default='travel')
blog_post = models.ForeignKey(BlogPost, on_delete=models.CASCADE, related_name='tags')
Then if you want to acces tags of a certain post in a view you would use:
blog_post = BlogPost.objects.get(pk=pk) # query the blog post you want the tags to
tags = blog_post.tags.all() # get the tags
Then simply add a form to each blog post where you would add a tag and save it to the related post. I'm not sure how you would do it an an admin interface though.

manytomany field not working django-cms

I am using django-cms
many to many field is working fine when i add plugins or update but
after publish page i didn't get any data where i add many to many field.
models are look like this
#python_2_unicode_compatible
class ClientLogo(CMSPlugin):
client_logo = models.ManyToManyField(LogoPluginModel, blank=True)
class LogoPluginModel(CMSPlugin):
title = models.CharField(max_length=100)
here field 'client_logo' will be disapper when i publish djagno-cms page
The relations need to be explicitly copied through the copy_relations method (see django-cms models manual). It's also advantageous to add a related_name property to the ManyToManyField, especially when a model contains multiple sets of foreign keys or ManyToManyFields.
#python_2_unicode_compatible
class ClientLogo(CMSPlugin):
client_logo = models.ManyToManyField(
LogoPluginModel,
blank=True,
related_name='client_logos',
)
class LogoPluginModel(CMSPlugin):
title = models.CharField(max_length=100)
def copy_relations(self, oldinstance):
self.client_logos.all().delete()
for logo in oldinstance.client_logos.all():
logo.pk = None
logo.showroom = self
logo.save()

Python Django how to retrieve specific objects

I've got this Post model at the moment:
class Post(models.Model):
title = models.CharField(max_length = 140)
body = models.TextField()
date = models.DateTimeField()
def __unicode__(self):
return self.title
If I've got different parts of a website (or a forum rather) that contain different posts, e.g. Discussion about basketball, and Discussion about football, if I wanted to return just posts concerning basketball or just posts concerning football, is the easiest way to just make a specific basketball_post model/football_post model or is there a more efficient way? Should I perhaps be storing the values differently?
Thanks
Django has a really good tutorial. It is about making a Poll app. In the first chapter the thing you want is discussed. It is about a Question that can have multiple Choices.:
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
class Choice(models.Model):
question = models.ForeignKey(Question)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
The foreignKey creates a relation between two models. The same can be done for a blog:
class Category(models.Model):
title = models.CharField(max_length=200)
class Post(models.Model):
category = models.ForeignKey(Category) # This is the important part.
title = models.CharField(max_length=200)
body = models.TextField()
date = models.DateTimeField()
def __unicode__(self):
return self.title
The ForeignKey relation lets you do really nice things:
basketball_posts = Post.objects.filter(category_title='Basketball')
But before we all tell you how it is done, I really recommend to do the tutorial. It introduces you to all important Django concepts: https://docs.djangoproject.com/en/1.7/intro/tutorial01/
Update
If you have a fixed set of categories that are not likely to change, than you can hardcode them and use field choices:
class Post(models.Model):
FOOTBALL = 'F' # Variable name and db_value
CRICKET = 'C'
INTRODUCTION = 'I'
CATEGORY_CHOICES = (
(FOOTBALL, 'Soccer'), # Variable name and display value
(CRICKET, 'Cricket'),
(INTRODUCTION, 'Hello my name is'),
)
category = models.CharField(max_length=1,
choices=CATEGORY_CHOICES,
default=INTRODUCTION)
...
https://docs.djangoproject.com/en/dev/ref/models/fields/#choices
One of the advantages of this 'choice machinery' over a CharField without pre defined choices is that you are sure what values end up in your database. This lets you query them, without worrying if your data is sane:
Post.objects.filter(category=Post.CRICKET)
Use the extra table if you need the freedom to create new categories in the future. Use field choices if you don't want (or need) that freedom.
I would suggest to just add a field which makes the post relevant to that certain topic:
class Post(models.Model):
title = models.CharField(max_length = 140)
body = models.TextField()
date = models.DateTimeField()
type = models.CharField(max_length=20) #<--- new field: e.g 'basketball','hockey'..
def __unicode__(self):
return self.title
example query:
#basketball posts
qs = Post.objects.filter(type__icontains="basketball")
then you dont need to have multiple models which also would be redundant.
Assuming all of the posts are in the same format, you could add another field to your model like "type". Different discussion forums could send a different values for that field when the post is added.
type = models.CharField(max_length=140, choices=['Football', 'Basketball', 'Baseball'])
Storing this would make it easy to filter which posts are which.
Post.objects.filter(type = 'Football')
Assuming that one post can be about only one sport, the better approach would be to have a foreign key relation between a model that stores data about a post with another model that stores the data about sports.
Something like this
class Sport(models.Model):
name = models.CharField(max_length = 200)
description = models.TextField()
def __unicode__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length = 140)
body = models.TextField()
date = models.DateTimeField()
sport = models.ForeignKey(Sport)
def __unicode__(self):
return self.title
This gives you the advantage of isolating the 'Sport' and the 'Post' models.You can add as many sports as you want, without any posts referring to it.
One more advantage is that you can add relevant information to the relevant models.
Eg:Suppose you want to add the information about "how many players are there in a team for sport x?". You can easily achieve this by adding a field "number_of_players" in the 'Sport' model without affecting the 'Post' model.
If you had to do this in one model, 'Post', then it would create lot of issues in terms of data consistency and other undesirable things.
Also, the query will look something like this:
posts = Post.objects.filter(sport__name = "Basketball")
PS:If your requirement is that a post can be tagged to multiple sports, then you can use ManyToMany field instead of a simple foreign key.
https://docs.djangoproject.com/en/dev/topics/db/examples/many_to_many/
You could assign your posts tags or category, and filter on those.
If you use the model approach what happens when you add more sports? You'll need manually add the sports in your code, using a tags or category approach allows you to handle it in the db, and would then allow you to filter on the tags/categories in your system

Django: Entering instances of classes with empty collections

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.

Django multiple tag field

I'm trying to find a good tutorial for django how to create multiple tags in a model.
For example:
class Tag(models.Model):
name = models.CharField()
class Sample(models.Model):
name = models.CharField()
urlA = models.CharField()
urlB = models.CharField()
tagA = models.ManyToManyField(Tag)
tagB = models.ManyToManyField(Tag)
I would like to display the tags as an input field and separate by ',' and split in the save method. So I'd like to see 2 different input for the 2 tag field.
If you have an easy way to do or know a good tutorial, please tell me! :)
Thank you guys!
Edit: you do not have to have the actual table sets over laid. You can generate any queryset you want to inn your views. Your url conf can be set up to display the detail view from multiple url. If i am still not understanding then please refine your question.
For having multiple anything tags categories your either going m21 or m2m. So when you create your tags you can add them one by one. Are you familiar with what the Django ORM has to offer with some of its admin functionality? Please give the documentation a good look through. Your approach to this problem is anything but reasonable. Not trying to rub you the wrong way I'm no genius. You would do something like so.
class Tag(models.Model):
title = models.CharField(max_length=250, blank=True)
slug = models.SlugField(blank=True
class Meta:
verbose_name = "tag"
verbose_name_plural = "tags"
ordering = ['title']
#models.permalink
def get_absolute_url(self):
return "/tags/%s/" % self.slug
class Entry(models.Model):
title = models.CharField(max_length=250, blank=True)
body = models.TextField()
tags = models.ManyToMany('Tag')
slug = models.SlugField()
#models.permalink
def get_absolute_url(self):
return "/blog/%s/" % self.slug
There's a little more code to be done for the EntryAdmin and the TagAdmin models, Many other things that can be done as well. I am not sure what you are trying to achieve with that if you could be more clear? Thank you, the above is a rough illustration of how I would approach it.
I found a solution from here:
https://dev.to/thepylot/how-to-add-tags-to-your-models-in-django-django-packages-series-1-3704
django-taggit is very useful for tagging.
It is
a reusable application that primarily offers you a Tag model, and a manager for easily adding tags to any model.
pip install django-taggit
After that, open settings.py and edit the installed apps section:
INSTALLED_APPS = [
...
'taggit'
]
After that, edit your model and add tags like this:
tags = TaggableManager()
The TaggableManager will show up automatically as a field in a ModelForm or in the admin.
Documentation: https://django-taggit.readthedocs.io/en/latest/index.html

Categories