xDjango Inner Join tables with queryset - python

I'm trying to INNER join 2 tables: Comments and Auth. So I store userid in Comments table and I need to pair it with the Auth.
I did with .raw(), but I don't want to do with the raw(), I have tried also other like get_objects_or_404 but that does not work either because of multiple queries.
Here is my query, works as excepted.
SELECT * FROM index_comment INNER JOIN auth_user WHERE index_comment.userid=auth_user.id
And here is my Comment model:
class Comment(models.Model):
content = models.TextField()
userid = models.IntegerField()
published = models.DateField(default=timezone.now)
postid = models.IntegerField()
Views.py
def readPost(request, postName):
content = get_object_or_404(Post, link=postName)
kategori = get_object_or_404(Category, id=content.category_id)
user = get_object_or_404(User, id=content.username_id)
if request.method == "POST":
form = sendComment(request.POST)
if form.is_valid:
formContent = strip_tags(request.POST["content"])
newComment = Comment()
newComment.content = formContent
newComment.postid = content.id
newComment.save()
return redirect('post',content.link)
else:
form = sendComment
args = {
"content": content,
"kategori": kategori,
"user":user,
"commentForm": form,
}
# return HttpResponse("cat.id")
return render(request, "theme/single.html", args)
And here is the forms.py
class sendComment(forms.Form):
content = forms.CharField(widget=forms.TextInput(attrs={"class":"form-control"}))
So I need to pair userid from Comments table to Auth id, and then get the username.

By setting up your models properly with a foreign key relationship (django docs) from index_comment.userid to auth_user.id, Django will handle the join for you and make the columns of the joined table(auth_user) available through the primary model (index_comment).
Something like:
from django.db import models
from django.contrib.auth.models import User
class Comment(models.Model):
content = models.TextField()
userid = models.ForeignKey(User,on_delete=models.CASCADE)
published = models.DateField(default=timezone.now)
postid = models.IntegerField()
will tie the userid in your comment table to the user table of django's built auth functionality. the name fields will be available to Comment like
comment.userid.username

Related

Django: How to write a function based view used for URL with parameter

I am learning Django, using function based views, and I am struggling with the following:
I have this path in urls.py
path('user/<str:username>',views.UserProjectList,name='user-projects')
that is supposed to show all the projects of the particular user (client). In order to reach it, username should be parameter of the function based view, however I am struggling how to write such view...
I have this:
def UserProjectList(request,username):
user = User.objects.get(username=username) #THIS IS WRONG and should return id of the user
#user = User.objects.filter(username=username) #also wrong
tag_list = ProjectTagsSQL.objects.all() #ProjectTagsSQL and ProjectSQL are connected
project_list = ProjectSQL.objects.filter(client=user) #ProjectSQL table has column client_id (pk is id in User) and table contains all the projects
context = {
'tagy' : tag_list,
'projecty' : project_list
}
return render(request, 'home_page/user_projects.html', context) #SHOULD THE PARAMETER BE INCLUDED HERE?
I tried to inspire with the code from class based view I found on the internets (thats is working for me but i didnt manage to connect it with ProjectTagsSQL as i managed in FBV, but that's a different problem) but i didnt manage
class UserProjectListView(ListView):
model = ProjectSQL
template_name = 'home_page/user_projects.html'
context_object_name = 'data'
def get_queryset(self):
user = get_object_or_404(User, username=self.kwargs.get('username'))
return ProjectSQL.objects.filter(client=user)
Could someone help me how to deal with such function based view please? As this solution its not working (will return nothing for any user)
Here is also the ProjectSQL model (and ProjectTagsSQL model) :
class ProjectSQL(models.Model):
id = models.AutoField(primary_key=True)
country = models.TextField()
city = models.TextField()
time_added = models.DateTimeField(default=timezone.now)
start_date = models.DateField()
end_date = models.DateField()
client = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
managed = False #https://docs.djangoproject.com/en/4.0/ref/models/options/
db_table = 'project'
class ProjectTagsSQL(models.Model):
id = models.IntegerField(primary_key=True)
project = models.ForeignKey(ProjectSQL, on_delete=models.CASCADE)
tag = models.ForeignKey(ProjectTagSQL, on_delete=models.CASCADE)
class Meta:
managed = False # https://docs.djangoproject.com/en/4.0/ref/models/options/
db_table = 'project_tags'
You need to write user.id so:
from django.shortcuts import get_object_or_404
def UserProjectList(request,username):
user = get_object_or_404(User,username=username)
tag_list = ProjectTagsSQL.objects.all()
project_list = ProjectSQL.objects.filter(client=user.id)
context = {
'tagy' : tag_list,
'projecty' : project_list
}
return render(request, 'home_page/user_projects.html', context)
Also, try to check template variables' name, whether you used same or not.
Note: Always append / at the end of every route so it should be path('user/<str:username>/'....
Note: Function based views are generally written in snake_case so it is better to name it as user_project_list instead of UserProjectList.

How to update only selected records in Django queryset like in admin panel actions? [duplicate]

I need to update the model according to the marked checkboxes in the django shape
How can I get only some of the table fields in a query
the "checked" line should be updated through the queryset
models.py
class moIn(models.Model):
date = models.DateTimeField(auto_now_add=True, verbose_name='')
dateUpdate = models.DateTimeField(auto_now=True)
ts = models.IntegerField(verbose_name='')
pl = models.IntegerField(verbose_name='')
rem = models.IntegerField(verbose_name='')
comment = models.TextField(max_length=200, verbose_name='', blank=True)
staffer = models.ForeignKey(User, on_delete=models.PROTECT, verbose_name='')
checked = models.BooleanField(verbose_name='', default=False)
checkedUser = models.ForeignKey(User, on_delete=models.PROTECT, verbose_name='', blank=True, null=True, related_name='checkedUser')
by clicking this checkbox, you will need to receive database records
forms.py
class checkForm(ModelForm):
checked = fields.BooleanField(required=False)
class Meta:
model = moIn
fields = {"id", "checked"}
views.py
def dashboard(request):
if request.user.groups.filter(name='DashBoardAccess').exists():
form = checkForm
f = tableDashFilter(request.GET, queryset=moIn.objects.all())
if request.method == 'POST':
form = checkForm(request.POST)
if form.is_valid():
tt = form.save(commit=False)
data = form.cleaned_data
field = data['checked']=True
f.qs.filter(checked=field).update(checked=True, checkedUser=request.user)
return HttpResponse('ok')
else:
context = {
'filter': f,
'form': form
}
return render(request, 'dashboard/index.html', context)
else:
raise Http404()
in a line in bold, you need to get only those lines in which the checkbox is marked
f.qs.filter(checked=field).update(checked=True, checkedUser=request.user)
You can get all the fields using ".values ()" for the queryset, and to use it with foreignKey, you need to explicitly specify the model fields:
f = tableDashFilter(request.GET, queryset=moIn.objects.values('id','date','ts','pl','rem','comment','checked','staffer__username','checkedUser__username'))
"Value" from the input, it is also going to be obtained through:
Since there can be several values (marked checkboxes), there will be a ".getlist"
checkID = request.POST.getlist('checked')
querySet filter:
f.qs.filter(id__in=checkID).update(checked=True, checkedUser=request.user)
in the html template through the loop, iterate over and insert into the input value of the model id

There is a way to get a value from views.py into nodels.py?(Django)

I'm making a little Django project of money management, I'm using a table layout, inside the tables there are many transactions. I have two SQL tables: "Table" and "Transactions" and I need that when I open the link of one specific table, I need to get just the items which were created in the table page.
Example:
I open 'table1' and inside it I create 'value1', 'value2','value4'
after, I open 'table2' and inside it I create 'value3' and 'value5'
after that, when I open the 'table1' page I need to show
'value1','value2' and 'value4'
and when I open 'table2', I need 'value3' and 'value5'
I wonder if there is a way to take the id of the table I'm inside in the moment and write it into the transactions form to make some kind of 'id', so I can filter the values by it id
Here are my files:
urls.py
from django.urls import path
import tables1.views as vw
urlpatterns = [
path('admin/', admin.site.urls, name = 'admin'),
path('mytables/', vw.mytables, name = 'mytables'),
path('',vw.home),
path('table/<int:pk>',vw.table, name = 'tableurl'),
path('newtable/',vw.newtable,name = 'newtable')
]
views.py
from .models import Table
from .forms import TableForm
def home(request):
now = {}
return render(request,'tables1/home.html',now)
def mytables(request):
data = {}
data['tables'] = Table.objects.all()
return render(request, 'tables1/mytables.html', data)
def table(request,pk):
form = TableForm(request.POST or None)
data = Table.objects.get(idd = pk)
print(data)
if form.is_valid():
form.save()
return redirect('mytables')
return render(request,'tables1/table.html',{'data':data, 'form':form}),pk
def newtable(request):
form = TableForm(request.POST or None)
if form.is_valid():
form.save()
return redirect('mytables')
return render(request,'tables1/newtable.html',{'form':form})
models.py
from .views import table
class Table(models.Model):
idd = models.AutoField(primary_key=True, default= None)
name = models.CharField(max_length=100)
date = models.DateField(auto_now_add=True)
time = models.TimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'Tables'
def __str__(self):
return self.name
class Transacao(models.Model):
mod = models
date = models.DateTimeField()
desc = models.CharField(max_length=200)
value = models.DecimalField(max_digits=7,decimal_places=2)
obs = models.TextField(null=True,blank=True)
class Meta:
verbose_name_plural = 'Transacoes'
def __str__(self):
return self.desc
forms.py
from .models import Table
from .models import Transacao
class TableForm(ModelForm):
class Meta:
model = Table
fields = ['name']
class TransacaoForm(ModelForm):
class Meta:
model = Transacao
fields = ['desc','date','value','obs'] ```
From my understanding of your question, you want a relation between Table and Transaction, where each Table contains (possibly 0 or more) transactions. This is a many-to-one relation that can be done by a Foreign Key. Read more.
I modified your code and added the foreign key to it. By adding the foreign key field name to the form you can set the table for each transaction when you create it. And when you need to get the transactions for a table you can do table.transacoes. The name transacoes is defined in the related-name attribute of the foreign key.
models.py
from .views import table
class Table(models.Model):
idd = models.AutoField(primary_key=True, default= None)
name = models.CharField(max_length=100)
date = models.DateField(auto_now_add=True)
time = models.TimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'Tables'
def __str__(self):
return self.name
class Transacao(models.Model):
# Forein key defined here
table = models.FogeinKey(Table, related_name='transacoes')
# Also I don't know what this is, you probably don't need it
mod = models
date = models.DateTimeField()
desc = models.CharField(max_length=200)
value = models.DecimalField(max_digits=7,decimal_places=2)
obs = models.TextField(null=True,blank=True)
class Meta:
verbose_name_plural = 'Transacoes'
def __str__(self):
return self.desc
forms.py
from .models import Table
from .models import Transacao
class TableForm(ModelForm):
class Meta:
model = Table
fields = ['name']
class TransacaoForm(ModelForm):
class Meta:
model = Transacao
# table added here
fields = ['desc', 'date', 'value', 'obs', 'table']
I managed to solve my problem by instead of saving the form data automatically in database with "form.save()", i """manually""" got the data from form using form.cleaned_data for each one of the form fields and saved that data into database using Transaction.objects.create() so that i could save the pk variable into the transactions table with the name of "tableid", that way, the app could link the primary key of each table page and link it to the transactions registered inside that page.

Django Model Not Saving All Data From Form

I currently have a Django form that saves data from a questionnaire against a user, where a user is stored as a Foreign Key from the Person model. I can successfully find the person from the Person class using get_object_or_404(), but when I try to save(commit=True), the data is not being saved in the database. See below for my code:
# models.py
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=100)
email = models.EmailField(max_length=254, primary_key=True)
tel_number = models.CharField(max_length=13, blank=True)
referral_code = models.UUIDField()
class Meta:
verbose_name_plural = 'People'
def __str__(self):
return str(self.referral_code)
class Questionnaire(models.Model):
user = models.ForeignKey(Person, related_name='questionnaire_person', on_delete=models.CASCADE)
... and some questionnaire questions here (CharFields and TextFields) ...
# views.py
def index_questionnaire(request):
template = 'questionnaire.html'
# load blank instance of template
questionnaire = UserQuestionnaire()
context = {
"questionnaire": questionnaire
}
# if user has submitted something, check form is valid
if request.method == 'POST':
answers = UserQuestionnaire(data=request.POST)
if answers.is_valid():
# submission is genuine so save as new entry to database
# get user's unique referral ID from URL
user_referral_id = request.GET.get('user')
# check legit person
try:
answers.save(commit=False)
answers.person = get_object_or_404(Person, referral_code=user_referral_id)
print('user found: {}'.format(answers.person))
answers.save(commit=True)
print('Questionnaire saved')
except:
print("user not found")
return render(
request,
template,
context
)
#forms.py
class UserQuestionnaire(forms.ModelForm):
class Meta:
model = Questionnaire
fields = (
'answers_1',
'free_text_1',
'answers_2',
'answers_3',
'answers_4',
'answers_5',
'answers_6'
)
widgets = {
'answers_2' : forms.RadioSelect(),
'answers_3' : forms.RadioSelect(),
'answers_4' : forms.RadioSelect(),
'answers_5' : forms.RadioSelect(),
}
So at the moment I'm drawing the user parameter from the URL, which is uuid.uuid4(). The print statement in the "try: except" bit successfully prints out the user UUID as expected, yet when submitted it doesn't save correctly. For further info, I am using the MultiSelectField() for one of the questionnaire questions.
If anyone has any suggestions as to why this might be, that would be amazing!
That is because asnwers.save(commit=False) creates another new object.
Do something like
f = answer.save(commit=false)
f.person = get_object_or_404(Person, referral_code=user_referral_id)
f.save()
No need to do f.save(commit=True) since the True is default.
for more info check docs:
docs.djangoproject.com/en/3.1/topics/forms/modelforms/

django add foreign key value after form submit

After a ModelForm has been submitted, how can I add a foreign key relation so that it validates?
models.py
class Comment(models.Model):
id = models.AutoField(primary_key=True)
activity = models.ForeignKey(Activity)
submitter = models.ForeignKey(User)
creation_date = models.DateTimeField(auto_now_add=True)
content = models.TextField()
forms.py
class CommentForm(forms.ModelForm):
content = forms.CharField(widget=forms.Textarea)
class Meta:
model = Comment
views.py
def index(request, id=None):
activity_instance = Activity.objects.get(pk=1)
submitter_instance = User.objects.get(id=1)
newComment = CommentForm(request.POST)
newComment.activity = activity_instance
newComment.submitter = submitter_instance
if newComment.is_valid(): # <-- false, which is the problem
I think you are mixing up form instance with model instance. your newComment is a form, assigning other objects as a form attribute will not make the form saving the foreign key(not sure where did you find this usage), because all form data is saved in form.data, which is a dict like data structure.
I'm not sure what does your form look like because you didn't exclude the foreign keys so they should be rendered as dropdowns and you could select them. If you don't want the user to select the foreign key but choose to assign the values as you currently do, you should exclude them in the form so form.is_valid() would pass:
class CommentForm(forms.ModelForm):
content = forms.CharField(widget=forms.Textarea)
class Meta:
model = Comment
exclude = ('activity', 'submitter')
views.py
def index(request, id=None):
activity_instance = Activity.objects.get(pk=1)
submitter_instance = User.objects.get(id=1)
comment_form = CommentForm(request.POST)
if comment_form.is_valid():
new_comment = comment_form.save(commit=False)
new_comment.activity = activity_instance
new_comment.submitter = submitter_instance
new_comment.save()
Django doc about save() method.

Categories

Resources