how to get id of an object from url of page django - django

i have created a list in which it shows the name of all groups present when you click it redirect to another page with group id, when i create a post i need to specify which group it is, i am getting the id in url of page but i have no idea how to define group object with that url,
views
def create(request):
if request.method == "POST":
name = request.user
author = request.user
message = request.POST['message']
message = comments(user=author,message=message,name=name,group_id=2)
message.save()
return HttpResponse('')
instead of group_id=2 or hardcode it , can i automatically take the id from url of the page like we do in request.user
models
class group(models.Model):
group_name = models.CharField(max_length=100)
group_user = models.ForeignKey(User,on_delete=models.CASCADE)
def __str__(self):
return f'{self.id} group'
class comments(models.Model):
userId = models.AutoField(primary_key=True)
name = models.CharField(max_length=100)
group = models.ForeignKey(group,on_delete=models.CASCADE,null=True)
user = models.ForeignKey(User,on_delete=models.CASCADE)
message = models.TextField()
date = models.TimeField(auto_now_add=True)
def __str__(self):
return f'{self.user} comments'
i have been trying day and night and couldnt solve, all the genius programmers out there pls give me a solution

urls.py
urlpatterns = [
path('create/<int:group_id>', views.create)
]
views.py
def create(request, group_id):
if request.method == "POST":
name = request.user
author = request.user
message = request.POST['message']
message = comments(user=author,message=message,name=name,group_id=group_id)
message.save()
return HttpResponse('')
As an example if you are running your app on localhost going to localhost:8000/create/1 will make group_id = 1, going to localhost:8000/create/2 will make group_id = 2 etc..

Related

Django - display and saving in a simple form

This is a very beginner-orientated question but I've been stuck on this issue all day.
I would like to load the data for a specific record and be able to save it (Submit button in a template) but i'm still trying to understand instances and the save method.
models.py
class model_essays(models.Model):
user = models.ForeignKey(User, default='1', on_delete=models.CASCADE)
title = models.CharField(max_length=100, default='')
date_added = models.models.DateTimeField(auto_now_add=True)
body = models.TextField()
def __str__(self):
return self.title
I understand the id is created automatically
forms.py
class frm_essays (forms.ModelForm):
class Meta:
model = model_essays
fields = ['title', 'date_added', 'body']
urls.py
urlpatterns = [
path('essay/<int:pk>', views.views_essay),
]
views.py {stuck here}
#login_required
def views_essay(request, pk):
if request.method == 'POST':
updatedForm = essay_detail(request.POST, instance=request.? {I want the ID of the essay})
if u_form.is_valid():
updatedForm.save()
messages.success(request, f'this essay has been updated')
return redirect('essay_detail')
else:
updatedForm = frm_essays(instance=request.{as above})
context = {
'updatedForm': updatedForm
}
return render(request, 'essay_detail.html', context)
On the decorator - I haven't gotten around to only allowing the users to view their own created essays, this would be the next large hurdle but not the issue I'm asking about.
Unless I am mistaken you are looking for the same ID as the pk (primary key). You have that passed in as an argument to your function.
You just need to query the instance from the DB.
def views_essay(request, pk):
essay = model_essays.objects.get(pk=pk)
if request.method == 'POST':
updatedForm = essay_detail(request.POST, instance=essay)
...
Note: essay will be None if the query based on the pk does not find an match in the DB.

django - upload file to a specific folder

I have a userprofile that captures the username and the group the user is assigned to. I want the uploaded files to be saved under the group name folder. The folders already exit at the media root, the files shoud be routed to these folder
I solved the problem by the solution given. Now the username is shown as a dropdown list on the upload page. I want only the logged it username to be shown or exclude even showing it
models.py
class uploadmeta(models.Model):
path = models.ForeignKey(Metadataform, on_delete=models.CASCADE)
user_profile = models.ForeignKey(UserProfile, on_delete=models.CASCADE, null=True, verbose_name='Username')
tar_gif = models.FileField(upload_to=nice_user_folder_upload, verbose_name="Dataset") # validators=[FileExtensionValidator(allowed_extensions=['tar', 'zip'])]
def __str__(self):
return self.request.user.username
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
Group= models.CharField(max_length=500, choices=Group_choices, default='Please Select')
def __str__(self):
return self.user.username
view.py
def uploaddata(request):
if request.user.is_authenticated:
if request.method == 'POST':
form = uploadmetaform(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('file_list')
else:
form = uploadmetaform()
return render(request, 'uploaddata.html', {
'form': form
})
else:
return render(request, 'home.html')
forms.py
class uploadmetaform(forms.ModelForm):
count = Metadataform.objects.all().latest('id').id #To know the id of latest object
data = Metadataform.objects.all().filter(id=count) #return the queryset with only latest object
path = forms.ModelChoiceField(queryset=data)
def __init__(self, *args, **kwargs):
super(uploadmetaform, self).__init__(*args, **kwargs)
count = Metadataform.objects.all().latest('id').id
data = Metadataform.objects.all().filter(id=count)
self.fields['path'] = forms.ModelChoiceField(queryset=data)
class Meta:
model = uploadmeta
fields = ['path', 'user_profile','tar_gif',]
You can use the upload_to argument in the FileField.
It accept a string representing the path where you want to store the file or you can pass in a function which let you add more details.
More info from the doc: https://docs.djangoproject.com/fr/2.2/ref/models/fields/#django.db.models.FileField.upload_to
You may need to add a foreign key form uploadmeta to UserProfile like :
user_profile = models.ForeignKey(UserProfile, on_delete=models.PROTECT)
Then you can use the following
def nice_user_folder_upload(instance, filename):
extension = filename.split(".")[-1]
return (
f"your_already_definied_folder/{instance.user_profile.group}/{file}.{extension}"
)
Then use it in uploadmeta FileField
doc = models.FileField(upload_to=nice_user_folder_upload, verbose_name="Dataset")

how to look over all form fields provided and updating the model

I've created a Django view that does 2 things:
Create a new account
Modify a account
Works:
Creating new account and submitting the HTML form data to the database. Also works: showing a prefilled HTML form if user wants to modify an account with the account data that is known in the database.
Doesnt work:
When the user submits his/her form to update an account (user modified the info in the form), nothing is updated in the database.
I know how to update one single static value in the database like so:
a = accounts.objects.filter(pk=account_id).update(name='static value here')
but I don't know how to update the database with all the form data that the user submits when using Django Modelforms. Does anyone knows how to update the database with the submitted form data?
Code
#login_required(login_url='/dashboard/')
def dashboard_accounts_new_modify(request, account_id=None):
if request.method == 'POST':
# POST DETECTED
form = MyModelForm(request.POST, request.FILES)
if account_id:
# POST DETECTED
# ACCOUNT ID FOUND
# USER WANTS TO MODIFY A ACCOUNT
# WITH THIS QUERY I CAN UPDATE 1 STATIC VALUE IN THE DATABASE
# HOW DO I UPDATE THE VALUES FROM THE FORM IN THE DATABASE?? :(
a = accounts.objects.filter(pk=account_id).update(name='static value here')
return HttpResponseRedirect('/dashboard/accounts/')
else:
# POST DETECTED
# ACCOUNT ID NOT FOUND
# USER WANTS TO CREATE A NEW ACCOUNT
if form.is_valid():
if request.POST.get("name").lower() == 'new':
raise Http404("New account name may not be named NEW.")
# DATAHASE QUERY: ADD NEW ACCOUNT TO DATABASE
form.save()
# REDIRECT
return HttpResponseRedirect('/dashboard/accounts/')
elif account_id:
# NO POST DETECTED
# ACCOUNT ID FOUND
# PREFILL FORM WITH DATA
try:
from django.forms.models import model_to_dict
a = accounts.objects.get(pk=account_id)
form = MyModelForm(initial=model_to_dict(a))
except:
raise Http404("Account not found.")
else:
# NO POST DETECTED
# MODIFICATION IS NOT DETECTED
# LOAD EMPTY FORM
form = MyModelForm()
return render(request, 'backend/base_accounts_new.html', {'Title': 'Accounts', 'form' : form})
Model
# Clientdatabase
class accounts(models.Model):
name = models.CharField(max_length=200)
url = models.CharField(max_length=200)
website_title = models.CharField(max_length=200)
website_h1_text = models.CharField(max_length=200)
website_h2_text = models.CharField(max_length=200)
website_search_text = models.CharField(max_length=200)
website_font = models.CharField(max_length=200)
website_footer_left = models.CharField(max_length=600)
website_footer_right = models.CharField(max_length=600)
website_color_code_search_button = models.CharField(max_length=200)
website_color_code_banner = models.CharField(max_length=200)
website_logo_height_pixels = models.PositiveIntegerField()
website_logo_width_pixels = models.PositiveIntegerField()
filepath_favicon = models.FileField()
filepath_logo_vector = models.FileField()
filepath_logo_normal = models.FileField()
filepath_background_1 = models.FileField()
filepath_background_2 = models.FileField(blank=True, null=True)
filepath_background_3 = models.FileField(blank=True, null=True)
filepath_background_4 = models.FileField(blank=True, null=True)
setting_background_1_active = models.BooleanField()
setting_background_2_active = models.BooleanField()
setting_background_3_active = models.BooleanField()
setting_background_4_active = models.BooleanField()
def __str__(self):
return self.name
class AccountsForm(ModelForm):
class Meta:
model = accounts
fields = '__all__'
You can do like:
from django.shortcuts import get_object_or_404
if request.method == 'POST':
if account_id::
account = get_object_or_404(accounts, pk=account_id)
form = MyModelForm(request.POST,request.FILES, instance=account)
if form.is_valid():
...
form.save()
return HttpResponseRedirect('/dashboard/accounts/')
else:
form = MyModelForm(request.POST, request.FILES)
if form.is_valid():
if request.POST.get("name").lower() == 'new':
raise Http404("New account name may not be named NEW.")
form.save()
Learn more about forms here

Django inlineformset_factory

I'm stuck on a problem with Django framework. In detail, user can create a Group and associate Member (>=1 && <=3) to the group. Each member is identified by email address (unique). However, the same member can partecipate with different name and surname in different groups. So I have a many to many relationship (using through) between Group and Member.
In my view I've an inlineformset. However when I submit the form I always get:
archi_groupmember.group_id may not be NULL
I've changed the widget for the MemberGroup form, because the user don't have to select a member from a select but he has to type the member's mail.
So I think I should persist the member just before to save the MemberGroup, but I don't know how to do it!
I'm totally new to Django, I'm following the docs.
Thank you all for any help!!
Here a page screenshot just to clarify: http://postimg.org/image/bndh5ug29/
Following my code.
Models.py:
class Group(models.Model):
user = models.ForeignKey(User)
limit = Q(active = True)
project = models.ForeignKey(Project, limit_choices_to = limit)
name = models.CharField(max_length=100)
code = models.CharField(max_length=100, unique=True)
def __unicode__(self):
return self.name
class Member(models.Model):
groups = models.ManyToManyField(Group, through='GroupMember')
email = models.EmailField(max_length=254, unique=True)
def __unicode__(self):
return self.email
class GroupMember(models.Model):
group = models.ForeignKey(Group)
member = models.ForeignKey(Member)
name = models.CharField(max_length=100)
surname = models.CharField(max_length=100)
views.py:
#login_required
#user_passes_test(first_login_check, login_url='/detail')
def partecipate(request):
from django.forms import TextInput
MemberFormSet = inlineformset_factory(Group, Member.groups.through, form=GroupMemberForm, can_delete=False, extra=3, widgets={'member': TextInput() } )
if request.method == 'POST':
form = GroupForm(request.POST)
member_set = MemberFormSet(request.POST)
if form.is_valid():
for form in member_set:
print vars( form['member'] )
group = form.save(commit=False)
group.user = request.user
group.code = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(10))
group.save()
member_set = MemberFormSet(request.POST, instance=group)
member_set = member_set.save(commit=False)
payment = Payment()
payment.group = group
payment.invoice = _createInvoice(group.project.id, group.id)
payment.save()
return HttpResponseRedirect("/")
else:
return render(request, "partecipate.html", { 'form': form, 'member_set' : member_set })
else:
form = GroupForm()
form.Meta.model.project.queryset = Project.objects.filter(active=True)
member_set = MemberFormSet(initial=[ {'name': request.user.first_name,'surname': request.user.last_name,'member':request.user.email} ])
return render(request, "partecipate.html", { 'form': form, 'member_set' : member_set })
What version of Django are you using?
Since 1.3 the help docs has an example of using inlineformset_factory. And the example (link below) clearly shows passing in an instance of the parent record. Without that, your formsets will not be linked to real data.
https://docs.djangoproject.com/en/1.7/topics/forms/modelforms/#using-an-inline-formset-in-a-view
I'm also suspicious of specifying the Member.groups.through table class as the child. I would think you should leave it as Member, because the through table is part of the internal machinery.

Django Match ForeignKey from ModelChoiceField to MySQL

I have a ModelChoiceField called outage_name. I also have a simple form that allows you to select the item from the list. The ModelChoiceField is pulled from a MySQL DB. This queryset is located in forms.py
outage_name = forms.ModelChoiceField(queryset = Outage.objects.filter(published = True)
The models.py is listed below.
from django.db import models
from django.contrib.auth.models import User
class Outage(models.Model):
outage_name = models.CharField(max_length=60, unique=True)
published = models.BooleanField()
def __unicode__(self):
return self.outage_name
class Detail(models.Model):
detail = models.CharField(max_length=60, unique=True)
user = models.ForeignKey(User)
outage = models.ForeignKey(Outage)
def __unicode__(self):
return self.outage
When I select from the list and submit the form I can't seem to figure out how to match outage = models.ForeignKey(Outage) that was selected on the list. To the correct outage_name. In my views.py I can hard code the id and it submits to the database and everything works fine.
def turnover_form(request):
if request.user.is_authenticated():
if request.method == 'POST':
form = TurnoverForm(request.POST)
if form.is_valid():
details = Detail.objects.get_or_create(
detail = form.cleaned_data['detail'],
user = request.user,
outage = Outage.objects.get(pk=1))
return HttpResponseRedirect('/turnover/user/')
else:
form = TurnoverForm()
variables = RequestContext(request, {'form': form})
return render_to_response('turnover_form.html', variables)
else:
return HttpResponseRedirect('/authorization/')
Any advice on how to match the id with the selected item would be appreciated. I'm sure my code is not very pythonic as I'm still learning.
outage = form.cleaned_data['outage'] # cleaned_data['outage'] is a model instance