I'm building an app that is similar to an address book. For one of my views, I have a list of Individuals. Each Individual has a Role which links them to their job title and employer. There are several different types of employers so this is a generic relation.
Using the ListView generic view, I have created a list of individuals that displays their name, their job title and their employer, i.e.
"Jimmy, Officer, Chase Bank"
"Mary, CEO, General Hospital"
I need the names of the companies to be links that go to the companies detail page.
The Problem
Since I have one template for this list, I am having a hard time understanding how to change the url based on what type of employer the individual has i.e. Bank or Hospital.
What Might Work
Should I write a function for the view that takes the employer content type and creates a variable? Or should I put the function under the Role model? I am a noob to python/Django and am not sure how to even write this.
I attempted to use if/else statements in the template, i.e. if bank, use this url, but it did not work. Probably because it is a generic relation and my query was not right.
In response to the comment below:
I'm not sure exactly what you meant by inheritance structures but here are a simplified version of my models;
class Individual(models.Model)
name = models.CharField(max_length=30)
class Bank(models.Model):
name = models.CharField(max_length=30)
staff = generic.GenericRelation('Role',
content_type_field='employer_content_type',
object_id_field='employer_id'
)
class Hospital(models.Model):
name = models.CharField(max_length=30)
staff = generic.GenericRelation('Role',
content_type_field='employer_content_type',
object_id_field='employer_id'
)
... and so on for each different employer
class Role(models.Model):
title = models.CharField(max_length=70)
job_holder = models.ForeignKey(Individual)
employer_content_type = models.ForeignKey(ContentType,
limit_choices_to={"model__in": ('venue', 'festival', 'artsorganization','bookingagent', 'managementcompany', 'mediaoutlet', 'otherorganization', 'presentercompany', 'publishingcompany', 'presenter', 'recordcompany', 'musician', 'ensemble')}, related_name="employer")
employer_id = models.PositiveIntegerField()
employer = generic.GenericForeignKey('employer_content_type', 'employer_id')
At one point I had all employers inheriting from a Company model. I changed it because each employer has different attributes which was making things very complicated.
Thanks!
I believe each kind of employer should be responsible for providing a URL to itself (see get_absolute_url). That is, each employee model supplies get_absolute_url to determine a URL for itself.
Then, you can simply use (in your template):
{{ individual.name }}
<a href="{{ individual.role.employer.get_absolute_url }}">
{{ individual.role.employer.name }}
</a>
It's simplified here since the "Role to Individual" relation is One-to-Many, but use whatever mechanism you use to determine the employer's name in this instance. If your list is of roles, you obviously just use role.employer and instead role.job_holder to get the individual etc.
Related
I'm currently stuck on how to do the following:
I want to track workouts and see the progress being made with the exercises.
Each workout has a name, body weight, date, and exercises.
I want to select the exercises when adding the workouts(exercises are already pre-created with a name and some tags), however, each workout is different, meaning the reps, sets, and weight for the exercise is different every time.
I'm not sure how to make a model for this.
I've added an image of a simple design I made to show what I'm after
Hope someone can help me, I'm pretty sure it's a simple solution however, my brain is stuck atm.
Image Of Design
First an foremost, I'd recommend reading through the Django models docs to get an idea of what models represent and how they work.
To address your question, I think you've correctly identified all of the information you need to create your models, so let's go through them step by step.
Architecture
It's helpful to take a step back and think about the entities in your app. Identify what they are, what attributes they posses and which of these attributes are atomic i.e. cannot be their own entity.
Workout - You mentioned that you want to track workouts with each one having name, body weight, date, and exercises. All of these attributes except for exercises seem to be atomic as they can be represented with fundamental datatypes (strings, floats, datetimes etc.). Moreover, one workout can have many exercises indicating that we need to abstract it into its own entity.
Exercise - You identified that exercises are pre-set and need to have a name and tags. A name is something we can represent with a string, however one exercise can have multiple tags, meaning it's not atomic (has a one-to-many relationship). This means we need to extract it into its own entity.
Tag - From what you said, a tag simply has one attribute which is a name that can be represented by a string. One tag can belong to many exercises.
You may be wondering where we are storing the reps, sets and weight data for each exercise in each workout. This is actually going to require an extra entity that stores the many-to-many relationship between Exercise and Workout. Let's call this Workout-Exercise.
With this information we could draw a Entity Relationship Diagram as such:
This gives us what we need to start creating Django models.
Models
Let's start with the Exercise and Tag entities. We can simply translate these directly into Django models:
from django.db import models
class Tag(models.Model):
name = models.CharField(max_length=200)
class Exercise(models.Model):
name = models.CharField(max_length=200)
tags = models.ManyToManyField(Tag)
Here we've created the two models and specified a many-to-many relationship between Exercise and Tag. This means that an Exercise object can have many Tag objects e.g. you can call exercise.tags.all() to get all of the tags for a given Exercise object.
The tricky part comes when we are creating the Workout-Exercise entity. When we use ManyToManyField in Django, it normally automatically creates a mapping model/table that we don't see. However, in the case where we want to store extra information about these relations (as we do in our use-case) we have to use a through model.
On this model we have to define the two foreign keys for the models we are linking along with the data types for the extra field data we want to store. In this case the foreign keys are Workout and Exercise, and the extra data are reps, sets and weight. The model definitions could therefore look like:
class WorkoutExercise(models.Model):
workout = models.ForeignKey(
'Workout',
on_delete=models.CASCADE,
)
exercise = models.ForeignKey(
Exercise,
on_delete=models.CASCADE,
)
reps = models.IntegerField()
sets = models.IntegerField()
weight = models.DecimalField(max_digits=5, decimal_places=2)
class Workout(models.Model):
name = models.CharField(max_length=200)
body_weight = models.DecimalField(max_digits=5, decimal_places=2)
date = models.DateTimeField(auto_now_add=True)
exercises = models.ManyToManyField(
Exercise,
through=WorkoutExercise
)
If you're confused about any of the model data type choices I've recommended, please take a look at Django model docs.
With this set-up you should be able to access and insert all of the data you need. If you need more information on how to access any of the many-to-many relationship data, please look at the Django many-to-many docs.
Sources
https://docs.djangoproject.com/en/3.2/topics/db/models/
https://www.1keydata.com/database-normalization/first-normal-form-1nf.php
https://en.wikipedia.org/wiki/One-to-many_(data_model)
https://docs.djangoproject.com/en/3.2/topics/db/examples/many_to_many
I have a basic blog app that has a Post model:
class Post(models.Model):
author = models.ForeignKey(
get_user_model(), null=True, on_delete=models.SET_NULL)
title = models.CharField(max_length=30)
content = models.CharField(max_length=30)
template_specific_entry = models.CharField(max_length=30)
I need users to be able to create a Post template with template_specific_entry field values, and then other users to use these templates to create new post records, updating title and content but not template_specific_entry.
See the example use case below:
I would like to retain the original Post templates in their original form, so multiple versions of that template can be used.
My question is: what's the most efficient way to go about creating this structure?
Should I create two models, PostTemplate and Post and somehow link the template_specific_values between them?
Since this is 'row level' functionality, is it better to do this via model methods, so templates and posts are stored in the same model? E.g. def createTemplate(self): and def createPost(self): referencing the same model?
In each case how would I actually implement this?
Your drawing is a very good way to understand the problem you're trying to solve. And in fact, it's also clearly showing how your models should be constructed. You have templates and posts and each post needs to be linked to one and only one template.
You can almost see your drawing as the blueprint for your models:
PostTemplate has a ForeignKey to User (since there's an author, in your example "Author1") and has some specific characteristics (template_specific_values although I would try to name this field differently). Note that you use plural here, so I'm wondering if this should be a CharField and not something else, like an ArrayField.
Post has a ForeignKey to User (the author) and to PostTemplate, so that one template can "have" many posts, but each posts only one template.
When the user has selected a template, and then writes the post, the fk of the post gets set to the chosen template.
Forms can be complicated in Django. Formsets can make you want to quit Django. I'm at that point.
What are the different use cases and considerations of which one(s) to use?
I'm looking for some better guidance as to when to use each factory, as they seem to depend on when you know what type of form, fields, and whether or not you are creating, editing, or deleting (individual forms entirely or the parent model altogether). I have read many walkthroughs, but am struggling to see the larger picture, especially as I am attempting to move from function based views to Class Based Views.
Below are some pseudo code with assumptions/restrictions to help you help me understand the differences. It may help to provide psuedocode, such as what kind of Form (ModelForm or regular) goes with the Formset, or what should be popped from the form, given this seems to be a trend for creating forms with relations.
Assuming you have some models:
class Dish(models.Model):
name = models.CharField(max_length=50)
class Meal(models.Model):
name = models.CharField(max_length=50)
dishes = models.ManyToManyField(Dish,
# through='OPTIIONALMealDishIntermediaryClassTable',
related_name="meal")
class Reservation(models.Model):
date = models.DateTimeField()
greeting = models.CharField(max_length=255)
meal = models.OneToOneField(Meal, on_delete=models.CASCADE)
class MealPhotos(models.Model):
photo = models.OneToOneField(Photo, on_delete=models.CASCADE, related_name='mealPhoto')
meal = models.ForeignKey(Meal, on_delete=models.CASCADE)
# optional, so a photo can be attached to a dish if the picture is just of the dish
dish = models.ForeignKey(Dish, blank=True, null=True, on_delete=models.CASCADE)
And you want to create a new Meal, you want to send a Reservation at the same time:
which factory would you use?
does it depend on if the forms are all ModelForms? (meaning how would you handle assignming the Meal its Reservation)
assuming:
at this stage you know which Meal it is, but you still have to make a Reservation at the same time/same view.
you don't know which Dishes you are going to cook, since the reservation will tell you.
MealPhotos won't exist yet since the meal isn't prepared yet.
You want to create the meal and the reservation on the same form/screen
Then later, you want to add some dishes, based on what the Reservation says:
which factory would you use?
does it depend on if the forms are all ModelForms?
assuming:
at this stage you know which Meal it is, and you have a Reservation
you are going to assign dishes to the meal based on the Reservation, and you have enough information to do so, and can use a ModelForm easily, but not required
Later, the person eating the dish wants to take some photos, and you don't know how many they will take
which factory would you use?
does it depend on if the forms are all ModelForms?
assuming:
we will require them to take at least two
we have access to the Meal, Reservation, and Dishes
a photo could optionally be assigned to a Dish
The difference between the 3 formset factories is basically:
formset_factory lets you render a bunch of forms together, but these forms are NOT necessarily related to a particular database models (this is not what you need, since you have models for everything)
modelformset_factory lets you create/edit a bunch of Django model objects together, for example, if you were managing the "menu" you could use a modelformset_factory(Dish, fields=('name'))
inlineformset_factory lets you manage a bunch of Django model objects that are all related to a single instance of another model. For example, if you wanted to manage all of the MealPhotos that were taken at a particular Meal, this is what you would use
To answer your specific scenarios:
If you wanted a page that created a single Meal and a single Reservation at the same time, without assigning any Dishes yet, you don't need any formsets. You could just use a ModelForm for Meal and a ModelForm for Reservation.
Later on, if you want to attach multiple Dishes to the Meal, you would use an inlineformset_factory(Meal, Dish) to edit multiple Dishes belonging to a single Meal
Since we are using an inlineformset_factory, we have to create the Meal instance in the view that renders the form. Something like this:
DishFormSet = inlineformset_factory(Meal, Dish)
bday_dinner = Meal.objects.create(name='30th Birthday dinner')
formset = DishFormSet(instance=bday_dinner)
For someone uploading photos of the Meal, you would use:
PhotosFormSet = inlineformset_factory(Meal, MealPhotos)
bday_dinner = Meal.objects.get(name='30th Birthday dinner')
formset = PhotosFormSet(instance=bday_dinner)
This tells Django that all the photos submitted are all linked to that one Meal, but allows the possibility of assigning each photo to a different Dish (via a dropdown in the form).
Note: In the first scenario, I haven't tested whether you the use of a ManyToManyField as Meal.dishes is supported by the formset factory. If it isn't, then you could simply use a ModelFormset(Dish) and after those are created, link them to the Meal in the Django view that process the form submission.
In my Django project I have a database that is populated from outside Django, but needs the Django functionality to display data in the database in a user friendly manner. The legacy database structure is as follows:
class SomeModel(models.Model):
#some fields
group_access = models.ForeignKey(AccessGroup,on_delete=models.CASCADE()
class AccessGroup(models.Model):
group_name = models.CharField(max_length=200)
The users have a custom User profile with manytomany relationship with group names assigned to the specific user:
class CustomUser(models.Model):
#some values
projects = models.ManyToManyField(AccessGroup)
Currently I am able to display data from all groups a user has access to, but what I am looking for is a way to create a drop down menu so that users can switch between groups without the need to log out or reenter group on every view.
You could try something like this:
AccessGroup.objects.filter(CustomUser__pk=1)
Or
CustomUser.objects.filter(AccessGroup__group_name='GropName')
https://docs.djangoproject.com/en/2.0/topics/db/examples/many_to_many/
you can extend the django user model, somthing like
from django.contrib.auth.models import User
class CustomUser(models.Model):
projects = models.ManyToManyField(AccessGroup)
class UserProfile(models.Model):
user = models.OneToOneField(User, unique=True)
custom_user = models.ForeignKey(CustomUser, unique=False)
class SomeModel(models.Model):
#some fields
group_access = models.ForeignKey(AccessGroup,on_delete=models.CASCADE()
class AccessGroup(models.Model):
group_name = models.CharField(max_length=200)
then something like this to get the data in your view
def index(request):
AccessGroup.objects.filter(user__id=persion(request.user).id)
I'll assume you know how to get the list of groups, and are just looking as to how to get this list into templates. If not, let me know and I'll explain that as well.
If you're trying to get a global variable into templates, there are really 3 main options:
Make a custom template tag that takes the current user as input, and generates this list as output.
Use Middleware to generate the list, and append it to the current context for each request
Use a method on your user class, or a mixin of it (really easy if you use a custom user class), and just call that method as user.method in your templates. Remember to exclude parentheses from the method call (only in templates), and keep in mind that this method shouldn't accept any parameters other than self.
Thank you everybody for getting me on the right track. What I ended up doing is writing a context processor for checking the user permissions:
#context_processors.py
def check_groups(request):
group_check = AccessGroup.objects.values('id','group_name').filter(projects=request.user.id)
return {
'group_check': group_check,
}
Afterwards I created a Bootstrap-select dropdown in my base.html
<select class="selecpicker">
<optgroup>
<option data-hidden="true">Choose group</option>
{% for grpup in group_check %}
<option val="group.id">{{ group.group_name }}</option>
{% endfor %}
</optgroup>
And the it is just a matter of users using it as means to switch access groups in views and passing the value via ajax to any other template views I come across.
Not the 100% what I was looking for, but it works and my users are happy.
What I want is to retrieve all the fields belonging to a Model of a foreign key.
My models for example:
class BaseProduct(models.Model):
name = models.CharField(max_length=256)
variant = models.CharField(max_length=256, default='N/A')
type = models.ForeignKey(ProductType)
class ProductType(models.Model):
name = models.CharField(max_length=256,blank=False,null=False)
sofa = models.ForeignKey(SofaProduct, blank=True, null=True)
toaster = models.ForeignKey(ToasterProduct, blank=True, null=True)
These are just examples, there can be any number of ProductType models each with any number of fields.
In my template I can display all the fields of the BaseProduct by using the BaseProduct ID. What I want is to display all the fields of the FK.
For example if type = sofa in BaseProduct, I need to retrieve and display all sofa fields as well as BaseProduct fields.
(disclaimer: I have a tendency to give really long answers. You'll have to forgive me for that)
First rule of schema design - It should reflect your real world business logic (not the actual business action mind you, just the implications of the relationships). For example, if I have a class Person I can create a class Pet with a foreginKey to Person which translates to - every person can have multiple pets.
If we apply that logic to your schema we see that ProductType is a class that has a foreignKey to both Sofas and Toasters, which means each Toaster can have multiple Sofas and vice versa. Last time I checked, I never heard of a Sofa that had a Toaster.
In other words - you need to think what you're actually trying to achieve here. I'm guessing BaseProduct is a basic class that has common fields, and Sofa and Toaster are different types of products. Since they are different, they have their own special fields, and shouldn't be related, so it makes sense to have them as separate models. So why do you even need ProductType? To define the name Toaster? You're already defining an entire model! Why do you need to keep its name on a different table (and not, say, some custom method that always returns "I am a toaster, hear me roar")?
My best guess is that you want to be able to define new types of products on the go. However, if you intend to keep them separated on the model level, then you'll have to create a model for each new product. And if you want to be able to simple define a new model with ProductType, then you either need to have one Product class to manage them all, or you want a complicated dynamic system that can create new models on the fly.
Let's break those options down:
Create a generic product and a type class, like you did there:
class ProductType(models.Model):
name = models.CharField(max_length=256,blank=False,null=False)
class Product(models.Model):
name = models.CharField(max_length=256)
variant = models.CharField(max_length=256, default='N/A')
type = models.ForeignKey(ProductType)
Now each product can only be of one type, and you can always create new types on the go. This of course means all Product objects will share the same fields, and is very limiting. You won't have the same flexibility for each type like you would before (no sofa-only fields), but on the other hand it will be easier to create dynamic types of objects - you just define a new ProductType and bam you have a whole new group of products.
Create a basic abstract Product model, and define a new sub-model for each new type of product. You'll have a lot more flexibility for each one, but defining new types will always require defining a new model and setting up a table for it. With this scheme you don't need the ProductType object at all because the different models define the different types (there's no need for duplicity).
You can create some kind of admin page for the process, but it's not going
to be very easy to setup, and you might find yourself eventually with too many tables
(which can be especially problematic if you need to sometimes query
on all products - you'll have to join a lot of different tables,
which is not very efficient).
Use a non-relational database with some dynamic-models know how and disco*
*ok, it's actually more complicated than that, but the explanation on how to combine them is way too long, even for my answer. If it seems over your head, forget about it. If you have some idea about how non-relation databases work, you can probably figure it out yourself
Your question is somewhat unclear.
I think you want Django modal forms to display all fields of an modal.
def ListForm(Forms.form):
model = MyModel
fields='__all__' #Sets display all
fk_name ="Model_to_use" #Is needed when your model has more then one fk
Django model form
You can use _set for accessing related objects. For example, if you have two models like these:
class MyModel(models.Model):
name = models.CharField(max_length=200)
somedata = models.CharField(max_length=200)
class AnotherModel(models.Model):
name = models.CharField(max_length=256,blank=False,null=False)
referral = models.ForeignKey(MyModel)
type = models.CharField(max_length=256,blank=False,null=False)
you can access the name field of AnotherModel with
>>> m = MyModel.objects.get(id=1)
>>> m.AnotherModel_set.all()[0].name
See: https://docs.djangoproject.com/en/dev/topics/db/queries/#related-objects
On a side note, you should probably rethink your models structure, as yuvi pointed out.