Django direction of Many-to-Many relationship - python

I have two simple models Article and Topic, and as you can guess every article can belong to one or more topics.
The main functionality of this little app is to show all articles for a specific topic that the user selected.
What model should have the ManyToManyField? For my use case, I would say it makes sense to put it in the Topic model. However, if I do that I would always need 2 queries if I add a new article (1 on the Article model, and 1 on the Topic model to make the relationship).
I found this generic rule, but it's not helping me much in this situation.

"Generally, ManyToManyField instances should go in the object that’s going to be edited on a form. In the above example, toppings is in Pizza (Article) (rather than Topping (Topics) having a pizzas (article) ManyToManyField ) because it’s more natural to think about a pizza (article) having toppings (topics) than a topping (topic) being on multiple pizzas (articles). The way it’s set up above, the Pizza (Article) form would let users select the toppings (topics)." -docs
Just quoting because it's interesting the doc's emphasis is more on the UI than the ORM.
Also you're probably already doing this by just in case, I like to interact with my app via the shell to try out different queries in situations like this.

I would say you work things top -> down. Which is the top level object should have the relation description (ManyToManyField).
Why? Look at things from user interface point of view. You present the list of TOPICS or FORUMS before you go into articles and threads. RESTful urls also follow this logic as urls usually have TOPIC/topic_id/post/post_id/ not the other way around. For this reason I think it makes sense to add ManyToManyField to Topic not post, to Forum not article/thread.
You also get to use cool django stuff like
Topic.objects.get(id = topic_id).select_related()
My 2 cents anyway.
Edit1
I do not follow this advice all the time. For example:
There is Person and there is Group, which is meant to identify bunch of Persons. Where to put manytomanyfield there? Django, has put the manytomany connection to its Person (django.contrib.auth.models class User via mixin) not Group. I have done it the other way around in one case. Why? Because i wanted users to be able to add Person's to Group in Group's view not Person's view. And i did not want to do something like looping through bunch of persons to add single group to each of them. Looking back at this i still do not know if it was bad or good decision because it would have brought me problems either way :P
So i guess i want to say that you should evaluate each case separately and always think ahead about what you want to do with each class and object in the future.
/Edit1

Related

Benefits of foreign key over integerfield

I'm not sure if this is an appropriate question here. I know the answer but I don't really know why, and I need proof when I raise this to my team.
We have a number of Blog Posts on a Django Site. It's possible to "clone" one of those blog posts to copy it to another site. The way the current developer did that was to take the pk of the original post and store it as an IntegerField on the cloned post as clone_source. Therefore to get a story's clones, we do:
clones = BlogPost.all_sites.filter(clone_source=pk)
It seems to me that this would be much better structured as a foreign key relationship.
Am I right? Why or why not?
Deleted objects
If you ever decided to delete the original post, you'd need a separate query to handle whatever you expect to do with the cloned posts instead of using the on_delete kwarg of a FK.
Its an extra query
As noted in the comments, foreign keys allow you to traverse the relationships directly through the ORM relationship methods.
Data structure visualisation tools
These won't be able to traverse any further down from an integer field since it will believe it is at a leaf node.
Throughout all of this though, the elephant in the room is that a "clone" is still just duplicated data so I wonder why you don't just let a blog post be referenced more than once then you don't need to worry about how you store clones.

Global Variables in Django Admin Site

This was my original question, but it was not answered and so I thought Id post again with some of the strategies that I have tried, and be a little more specific.
I want to create a dynamic admin site, that based on if the field is blank or not will show that field. So I have a model that has a set number of fields, but for each individual entry will not contain all of the fields in my model and I want to exclude based on if that field is blank. My project is about bridges, and so to put it in practical terms I have a model that has every bridge part in it (this roughly is equivalent to 100), but each individual bridge (mapped to each unique brkey) will not have all 100 bridge parts. And so, I can prepopulate all of the fields it does have, but then the admin site has 100 other fields, and I would like to not display those fields that were not used on my admin site for that specific bridge, but those fields will differ with pretty much every bridge.
Like I said before, I have a unique bridge identifier(a unique 15 digit string), that correlates to each bridge, and then all of the various different variables that describe the bridge.
I have it set up now that the user will go to a url with the unique bridgekey and then this will create an entry of that bridge. So (as i am testing on my local machine) it would be like localhost/home/brkey and that code in my views.py that corresponds to that url is
Is this a final route that I have to take? I am very new to JavaScript and so I do not want to take this route but I will if I have to. Also does Django use Javascript in anyway that is syntactically different? If so I cannot find any Django documentation on incorporating Javascript into my admin site.
A final option that I have exhausted is to use global variables. Instead of having the url that creates the entry in my Views.py, I placed it in my admins.py, and had my modelAdmin class in there as well, so like this.
admins.py
-set up global variable
bridgekey_unique = " "
If I can find a way to either pass that unique bridge key to my modelAdmin class, or figure out if that said field is blank because the bridge doesnt have that part, I will be able to achieve what I want without using Javascript. I have tried a lot of variations of all two of theses strategies to no avail, but have not tried the JavaScript idea as I dont really know any javascript at all.
Sorry for the lengthy post, but people said I wasnt specific enough. Any help would be greatly appreciated.
I didn't read all of that - sorry, there's too much. But I did notice your comment that you expect to access in your modeladmin definition a variable that you set in your view. That can't possibly work.
Anything at class level is always executed when the module containing the class is first imported. That is when the server process starts up, so there is no possible way anything done in the view can have happened yet.
You almost never want to have any logic at class level. You need to put it in methods, which are called at the relevant time. In this case, you probably need to use the get_fields method.
Edit
Looking further up at your attempt at a get_fields method, I can't see at all what you are trying to do here. 'prestressed_concrete_deck' is a literal string, and could never be None, so neither of your conditions can ever be true. And as to your question about what the parameters are, the documentation for that method explains clearly that obj is the object being edited.

multiple users and Django

Starting to learn Django, not sure how to deal with multiple users and user types. What I would like to do is have a signin page where users of type A, B or C can log in (or new users can register as type A or B) and depending on their type they are presented with a different site. Furthermore, users of types A and B can actually be organized in groups within their own type and across types. So B1 and B2 may be only assigned to A1 or a group 'GA' which contains members {A2, A1, A3}.
The main goal is to create a site where people can posts question to specific experts or to the general public. When the experts log in they would only be presented to the users assigned to them and if they don't know the answer they could contact other experts or pass the question on to a larger group of experts say GE = {E1, E3, E6}.
There may already be tool out there to do this and I am complete oblivious to it. As of now we're just going to write it from scratch, and Django seemed like a good tool to use.
Any suggestions are helpful.
Sounds like quite the task you have! The first step is to use a Custom User Model, which will take the built-in django user model and allow you to extend it flexibly. I would suggest extending from the AbstractUser.
When you have your user authentication working you can add fields to the users to categorize them how you want.
Your explanation of what you're trying to do after that in the view logic is a little confusing so I'm going to let you figure that part out, but building a custom user model should get you going in the right direction.
It sounds to me that you are building something like a task management system. Where questions are like tasks, and the experts are like the assignees of tasks.
There are two approaches.
APPROACH 1 - use the django authentication system
Suppose you already know how to create users, authenticate them and log them in.
Create user groups and assign permissions to each group (You could either do this through the django admin or through code)
In the views.py, output different contents based on the permission that the logged in user has.
APPROACH 2 - custom build it
Create a Model for User Type and a Model for User (you can either use the default User model or extend it)
Assign each question to a specific User Type.
In the views.py, determine what questions to display based on the User Type of the logged in User.
APPROACH 2 is recommended because it's more flexible and scalable, given that you will extend your programme with more functions in the future.
I think you should have the basic ideas to start with it. Good luck.

Create portfolio backed skill-set in django ORM

I have a specialized User class that inherits from django.contrib.auth.models.User. Now, this User class will have tags associated with it, for example: Blogger, French Cuisine Cook, Python Programmer.
Ideally, what I want to do, is have each of these traits backed up by something that they have done, ideally a PortfolioItem. So, a User will have a set of tags, and these tags, and the relationship with each of these tags is going to be understood through these PortfolioItems. How would one achieve something like this using the django ORM?
Please note, that the tags are generic, however, the portfolios behind each of these tags are unique to every user.
How would one go about doing, this using the through variable in django ORMs.
UPDATE
I've tried simple adding PortfolioItem as the through variable, but in that case you will need to create a unique tag each time you want to add a list of portfolio item. The thing is I want tags to be generic.

Design ideas for a webapp in Django

I'm working on a user based, social networking type of web application in Django. It's my first one so I would like to make sure I'm using some good practices.
Currently the web app supports two kinds of users. This is represented by two different Groups. When I register a user I assign them to one of these two groups. I also have two apps, one for each type of user. The apps handle whatever things are distinct to a particular type of user. I have another app that handles the actual authentication. This app uses Django's built in User type and assigns them a UserProfile. The two different types of users have their own profiles which extend/inherit from UserProfile.
This works reasonably well, and is fairly reusable since the authentication app can pull the user type from the url and figure out which type of user to create. Since the groups are named conveniently, they can be added to the correct group too.
Is this the best way or are there more preferred, tried and true ways to handle this? It seems like a pretty common enough scenario. I don't want to continue incorrectly reinventing the wheel if I don't have to.
I was thinking of adding another app called, common, or something which would handle things that are common to all users. For example, viewing a users profile page might be something anyone who is logged in might want to do, regardless of what type of user they are.
Thanks!
Easy part first, with 2) you're spot on. That would be the simplest and most effective way of doing that. It makes sense instead of replicating functionality across both applications to have one app that handles things that are common to both user types.
Back to 1)
With both profiles extending from UserProfile, you'd run into the issue of (if you were using get_profile() on a User object - see http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users) that you'd get back just a UserProfile object, not knowing which group the user actually belongs to based on the object received. This is because they both extend UserProfile but UserProfile would not be able to be (I believe) abstract, because you want every User to have a pointer to a UserProfile object which may actually be a UserGroup1 or a UserGroup2 object.
What I would suggest you do is make two seperate Models, that do not extend from the same Model (out of necessity): Group1 and Group2. You would store the information that is common to both profiles in the UserProfile of the User object. Then in the UserProfile you would have a ForeignKey to both a Group1 and a Group2 object:
group1 = models.ForeignKey(Group1, blank=True, null=True)
You would have to do the logic checking yourself, to ensure that only one is ever valid (you could just do this in an overridden save() method or something), but then to grab all of a user's data at once, and also know which group they are on you could do the following:
User.objects.filter(username='blahblah').select_related('profile', 'profile__group1', 'profile__group2')
Only one query to the database would give you all the information you'd need about a user, and you'd also know which group they are in (the one that isn't 'None').
I hope that helps.
P.S. I am assuming in this that groups don't just have unique data to each other, but also unique functionality.

Categories