Model not defined - python

I defined a Question model with a description and a foreign key.
class Question(models.Model):
user = models.ForeignKey(
User,
verbose_name="User",
default=None
)
description = models.CharField(
max_length=60,
#verbose_name=_("Description"),
)
After that, I ran the migrations.
Then, in views.py I created a method which accesses objects of this model:
def own_questions(request):
questions = Question.objects()
return JsonResponse(questions)
The problem is that when I access the URL /questions corresponding to this method, I get:
NameError at /questions/
global name 'Question' is not defined
Why is this happening?

Probably because you haven't imported
from .models import Question
into your views.py

You need to import Questions in your views.py:
from app.models import Question
Also, questions = Question.objects only give you the queryset manager and you can't call that, instead for all questions, you need:
questions = Question.objects.all()
Edit:
I shouldn't assume what you are trying to query from model Question, so here's django doc about how to write ORM for queries.

Related

How to call function from views.py to models.py?

Problem
I'm new in Django, I have a function to retrieve foreign key object in views.py and I want to call this function to models.py, is there any way to do this?
views.py
def get_fk(request):
if request.method == 'POST':
category = itemCategory.objects.get(pk=request.POST.get('idItemCat'))
return category
models.py
class MyUser(AbstractUser):
pass
class ItemCategory(models.Model):
idItemCat = models.CharField(primary_key=True max_length=5)
nameCategory = models.CharField(max_length=150)
class ItemCode(models.Model):
idItemCode = models.CharField(primary_key=True, editable=False, max_length=20)
idItemCat = models.ForeignKey(ItemCategory, on_delete=models.DO_NOTHING)
What I've tried
To import a function usually in django like this from .views import get_fk, but every time I did that it doesn't work and getting this error, it said that my custom user has not been installed.
django.core.exceptions.ImproperlyConfigured: AUTH_USER_MODEL refers to model 'aset_app.MyUser' that has not been installed
Even though in my settings I've already installed my custom user
AUTH_USER_MODEL = 'aset_app.MyUser'
I know to use method request is supposed to be in views.py. But when I've tried to put this function inside models.py I'm getting another error it said
get_fk() missing 1 required positional argument: 'request'
If my question isn't clear enough, please let know...

Django Dynamic Fields Within A Form

A requirement for my app is to give user's capability to create a survey. For each survey, the user should have the capability to add any number of questions. I am trying to achieve this by first defining my models and a form.
# models.py.
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
def __str__(self):
return self.question_text
class Survey(models.Model):
survey_name = models.CharField(max_length=200)
questions = models.ForeignKey(Question, on_delete=models.CASCADE)
def __str__(self):
return self.survey_name
#forms.py
from django import forms
class Survey(forms.Form):
survey_name = forms.CharField(required=200)
#TODO: define questions
I am stuck. In my form module, how do I define the one to many relationship between the survey and questions in order for the user to add and define questions for each survey they create.
You can follow this tutorial to make dynamic forms dynamic form using django
or you can use javascript dynamic input using javascript to let user creat as many field wish. and get those field on view using request.POST.getlist("html input field name") and then insert onto model.

How do you use ManyToManyFields between apps without producing circular imports?

I have two apps, users and posts, with the models CustomUser and Block in users, and a model Post in posts. I'd like to created a "bookmarked" ManyToMany field for the User, so that they can bookmark any posts they want. It would look something like:
class CustomUser(AbstractUser):
...
neighbors = models.ManyToManyField("CustomUser", blank=True)
blocks = models.ManyToManyField("Block", blank=True)
bookmarked = models.ManyToManyField("Post", blank=True)
...
As you can see, I have quite a few ManyToMany fields already, but they were all for models from the same app users. As for my Post class:
class Post(models.Model):
...
author = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
block = models.ForeignKey(Block, null=True, on_delete=models.SET_NULL)
...
I already imported two models from the users app, CustomUser and Block, into the posts app. I understand that by importing Post into users' models.py, it creates a circular import, at least, it gives me the following error:
ImportError: cannot import name 'CustomUser' from partially initialized module 'users.models' (most likely due to a circular import)
Is there a way to prevent this? I know an option is to just create the bookmarked attribute in the Post model instead of the User model, but I'm reluctant to do so simply because it's a little weird to me personally. Do you know of any other options, or will I have to create the bookmarked attribute in Post as opposed to User?
You can connect the FK relation by using a string as,
author = models.ForeignKey('app_name.CustomUser', on_delete=models.CASCADE)
so that you don't have to import the related model

How to connect models from different apps in Django?

I have a few apps within my Django project. There are two apps that I am currently working with "Application" and "User" and I have two questions related to models:
Question 1:
I want to design it in such a way so that external users submit their contact form on Application/templates/Application/Apply.html and the info would get added to the database. Internal users would be able to add external users as well but from a different template: User/templates/User/AddNewContact.html
I am able to add a new contact from an internal user's perspective:
User/models.py
class Contact(models.Model):
ContactName = models.CharField(max_length = 250, default='')
ContactResidence = models.CharField(max_length = 250, default='')
Tel = models.CharField(max_length = 250, default='')
def get_absolute_url(self):
return reverse('User:ContactDetails', kwargs={'pk': self.pk}
)
def __str__(self):
return self.ContactName
class Locations(models.Model):
contact = models.ForeignKey(Contact, on_delete=models.CASCADE)
Country = models.CharField(max_length=250, default='')
def __str__(self):
return self.Country
I was going to just copy this model and paste it into Application/models.py but there are two problems:
1) I don't want external users to be directed to URL: User:ContactDetails and technically, it is not going to work out because I will build the authentication later on.
2) I feel that by copying and pasting I am breaking the 'don't repeat yourself" rule.
Should I connect two models using the foreign keys? What are the best practices in this case?
Question 2
Am I working with one-to-many relationship according to the model provided? I want to have one contact with his personal info (tel/email/address) and a number of branch locations across the world associated with that contact.
To be used a relationship one to many, you can be doing as after:
On models of father app (father table):
class Department(models.Model):
dept_id = models.AutoField(primary_key=True)
On models of child app (child table):
from appname.models import Department
class Office(models.Model):
office_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=200)
dept = models.ForeignKey(Department, on_delete=models.CASCADE)
It helped me.
Question 1: Well, you don't need to copy paste the model. You can use models from other django apps anytime, just need to import it. Basically what you should do is, instead of linking the url directly to the template in the Applications app, you should connect it to a view. In the view file you can import the models from User.models import *, and use them normally.
Question 2: As far as I understand the question your structure provides what you want: one contact (with personal info) associated with several countries. Except that you should replace Agent by Contact in contact = models.ForeignKey(Agent, on_delete=models.CASCADE)
Question 1: Note that the 'get_absolute_url' method is only called if you don't provide a success url in your view. If you are using a CreateView or FormView you can specify the success url by overriding the get_success_url method, for example:
class ContactCreateView(CreateView):
model = Contact
fields = ['ContactName', 'ContactResidence', 'Tel']
def get_success_url(self):
if not self.request.user.internal: # e.g. internal is a User bool field
return HttpResponseRedirect('some/external/url/')
return super().get_success_url() # call get_absolute_url model method.
The DRY principle is respected.
Question 2: Yes, the question you need to ask yourself is 'does a model instance (In this case Contact) have many instances of another model (Location)?' If the answer is yes, then the M2M field should go into your Contact model. See the django docs explaining the pizza/toppings example.
The apps should be in the same project and you can import one model as:
import appName.models or
from appName.models import ClassName
In app2 models you can use foreignKey or manyTomany after importing the class:
from appsName.models import ClassName
class Person(models.Model):
con = ForeignKey(ClassName)

Filter list of objects by self.request.user in Django

I cannot get this to work:
class MyView(generic.ListView):
context_object_name = 'my-model-list'
template_name = 'my_models.html'
def get_queryset(self):
return MyModel.objects.filter(user=self.request.user)
I have also tried
return MyModel.objects.filter(user=User.objects.filter(name=self.request.user))
It seems that self.request.user is returning a name. The error I get is
Cannot query "a": Must be "User" instance.
The user's name is "a".
My model is
from .models import User
class MyModel(models.Model):
user = models.ForeignKey(User)
Can anyone help me?
Thank you in advance.
Your code as shown is correct. The problem is that you are defining your own User class and Django does not know how to handle it when making requests.
The easiest way to do this would be to use the Django User. If you insist on using your own User Class you will need to modify that class to properly inherit from the Django User and a few other things (there are a few StackOverflows on that).
In your ./MyModel/models.py you will want to import User as such:
from django.contrib.auth.models import User
Leave your other models and your views as is (unless they also import User).
You may also have to update your settings file to look something like this (This may not be fully correct):
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
)
Don't forget to migrate your DB after making these changes.
you are inheriting the User model the wrong way.
Use from django.contrib.auth.models import User instead.
You can use self.request.user.mymodel_set.all() to get all Querys of current user
from .models import User
class MyModel(models.Model):
user = models.ForeignKey(User)
class MyView(generic.ListView):
context_object_name = 'my-model-list'
template_name = 'my_models.html'
def get_queryset(self):
return self.request.user.mymodel_set.all()

Categories

Resources