how to set relevent foreign key django in form - django

I want to submit a video section-wise. I create SectionVideo When I want to create a Video I want to set my Course name by default and want to show a relevant Section.
Course
class Course(models.Model):
instructor = models.ForeignKey(UserProfile,on_delete=models.CASCADE)
name = models.CharField(max_length = 50 , null = False,unique = True)
slug = models.CharField(max_length = 50 , null = False , unique = True)
Section:
class SectionVideo(models.Model):
course = models.ForeignKey(Course , null = False , on_delete=models.CASCADE)
name = models.CharField(max_length = 50 , null = False)
slug = models.CharField(max_length = 50 , null = False )
serial_number = models.IntegerField(null=False)
Video:
class Video(models.Model):
section_video = models.ForeignKey(SectionVideo , null = False , on_delete = models.CASCADE)
course = models.ForeignKey(Course , null = False , on_delete = models.CASCADE)
title = models.CharField(max_length = 100 , null = False)
video_description = models.CharField(max_length = 500 , null = True)
How can I make my create form for Video model?

You need to get the course(id) and the section(id) from a user.
Option 1. A user can select a course and a section in forms.
forms.py
from django.forms import ModelForm
from .models import Course, SectionVideo, Video
class VideoForm(ModelForm):
class Meta:
model = Video
fields = ['section_video', 'course', 'title', 'video_description']
views.py
from django.shortcuts import render
# Create your views here.
from .models import Course, SectionVideo, Video
from .forms import VideoForm
from django.forms import modelform_factory
# Create your views here.
def index(request):
# Both forms are functionally identical.
form = modelform_factory(Video, fields=('section_video', 'course', 'title', 'video_description'))
# form = VideoForm()
return render(request, 'templates/form.html', {'form': form})
Option 2. Getting the course(id) and the section(id) via video creating process, and assigning that parameters to form using initial
urls.py
If you get parameters from query, you don't need urls.py.
from django.contrib import admin
from django.urls import path
from zayed import views
urlpatterns = [
path('admin/', admin.site.urls),
path('zayed/<int:course_id>/<int:section_video_id>/', views.index, name='index'),
]
views.py
from django.shortcuts import render
# Create your views here.
from .models import Course, SectionVideo, Video
from .forms import VideoForm
# Create your views here.
def index(request, course_id, section_video_id):
form = VideoForm(initial={'course':course_id, 'section_video': section_video_id})
return render(request, 'templates/form.html', {'form': form})

Related

Reversing in Django - Trying to Reverse from Update View to Detail View in Django

I am trying to reverse to the Detail View after the Update View and to List View after Delete View. How can I implement this. I am getting an error reverse not defined.
Thanks
#Contents of Models.py
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
# Create your models here.
class Profile(models.Model):
OPTIONS_PROFILE_TYPE = (
('single', 'Single'),
('family', 'Family'),
)
OPTIONS_LOCATIONS = (
('USA', 'USA'),
('Canada', 'Canada'),
)
user = models.OneToOneField(User, on_delete=models.CASCADE, help_text='User Name')
display_name = models.CharField(null=True, max_length = 16, help_text='Optional Display Name' )
profile_type = models.CharField(null=True, choices=OPTIONS_PROFILE_TYPE, max_length=10)
location = models.CharField(null=True, max_length = 30, choices=OPTIONS_LOCATIONS, help_text='Optional Location')
biography = models.CharField(null=True, blank=True, max_length = 500, help_text='Optional Biography')
# Metadata
class Meta:
ordering = ['profile_type']
# Methods
def get_absolute_url(self):
#Returns the url to access a particular instance of MyModelName.
return reverse('profile-detail', args=[str(self.id)])
def __str__(self):
#String for representing the MyModelName object (in Admin site etc.).
return self.user.username
#Contents of Views.py
from datetime import datetime
from django.shortcuts import render
from django.urls import path
from django.http import HttpRequest
from .models import Profile
from django.views.generic import FormView, CreateView, DetailView, UpdateView, DeleteView, ListView
from django.shortcuts import redirect
from django.urls import reverse
class ProfileListView(ListView):
model = Profile
def get_context_data(self, **kwargs):
# Call the base implementation first to get the context
context = super(ProfileListView, self).get_context_data(**kwargs)
# Create any data and add it to the context
context['title'] = 'Users'
context['message'] = 'given below is a list of all users'
return context
class ProfileCreateView(CreateView):
model = Profile
fields = ['user', 'display_name', 'profile_type', 'location', 'biography']
def get_context_data(self, **kwargs):
# Call the base implementation first to get the context
context = super(ProfileCreateView, self).get_context_data(**kwargs)
# Create any data and add it to the context
context['title'] = 'Create User'
context['message'] = 'please use the form below to create the user'
return context
class ProfileDetailView(DetailView):
model = Profile
def get_context_data(self, **kwargs):
# Call the base implementation first to get the context
context = super(ProfileDetailView, self).get_context_data(**kwargs)
# Create any data and add it to the context
context['title'] = 'User Detail'
context['message'] = 'given below are the details of the user'
return context
class ProfileUpdateView(UpdateView):
model = Profile
fields = ['user', 'display_name', 'profile_type', 'location', 'biography']
def get_success_url(self):
return reverse('profile-detail', kwargs={'pk' : self.object.pk})
def get_context_data(self, **kwargs):
# Call the base implementation first to get the context
context = super(ProfileUpdateView, self).get_context_data(**kwargs)
# Create any data and add it to the context
context['title'] = 'Update User'
context['message'] = 'please use the form below to update the user'
return context
class ProfileDeleteView(DeleteView):
model = Profile
CONTENTS OF URLS.PY
from datetime import datetime
from django.urls import path
from django.contrib import admin
from django.contrib.auth.views import LoginView, LogoutView
from app import forms, views
from app.views import ProfileListView, ProfileDetailView, ProfileCreateView, ProfileUpdateView
urlpatterns += [
path('profiles/', views.ProfileListView.as_view(), name='profiles'),
path('profile/<int:pk>', views.ProfileDetailView.as_view(), name='profile-detail'),
path('create/', views.ProfileCreateView.as_view(), name='create'),
path('edit/<int:pk>/', views.ProfileUpdateView.as_view(), name='update'),
The error I am getting is - Reverse Not Defined when using the update view. I tried looking up and the solution which I have: Create View reverse to DetailView
requires me to migrate the get success url method to the views section. Is it possible to avoid this?

how to render django forms manually?

am new in Django. Does anybody know how to implement manual?
I have newsletter app:
newsletter/views.py
from django.shortcuts import render
from .forms import NewsUserForm
from . models import NewsUsers
# Create your views here.
def newsletter_subscribe(request):
if request.method == 'POST':
form = NewsUserForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
instance = form.save(commit=False)
if NewsUsers.objects.filter(email=instance.email).exists():
print('your email Already exists in our database')
else:
instance.save()
print('your email has been submitted to our database')
else:
form = NewsUserForm()
context = {'form':form}
template = "home/base.html"
return render(request, template, context)
newsletter/models.py
from django.db import models
# Subscribe models.
class NewsUsers(models.Model):
name = models.CharField(max_length = 30)
last_name = models.CharField(max_length = 30)
email = models.EmailField()
date_added = models.DateField(auto_now_add=True)
class Meta:
verbose_name = "NewsUser"
verbose_name_plural = "NewsUsers"
def __str__(self):
return self.email
newslettter/urls.py
from django.urls import path
from .views import newsletter_subscribe
app_name = 'newsletter'
urlpatterns = [
path('subscribe', newsletter_subscribe, name='subscribe'),
]
How to render this django forms manually, from third app to home template?
And i have in home app base template with following code:
home/templates/base.html
How to use this form on this template?

How to save signed in username with the form to database? Django

All other data is saved ideally but as shown below, the user id part shows as a pull down bar and a null value which should be a signed-in username.
What's wrong with my code?
The database page
Here's my code.
views.py
from .models import Markers
from .forms import AddMarkersInfo
from django.http import HttpResponse
def addinfo(request):
if request.method == 'POST':
mks = AddMarkersInfo(request.POST)
if mks.is_valid():
submit = mks.save(commit=False)
submit.user = request.user
submit.save()
name = mks.cleaned_data['name']
address = mks.cleaned_data['address']
description = mks.cleaned_data['description']
type = mks.cleaned_data['type']
lat = mks.cleaned_data['lat']
lng = mks.cleaned_data['lng']
Markers.objects.get_or_create(name=name, address=address, description=description, type=type, lat=lat, lng=lng)
return render(request, 'home.html', {'mks': mks })
else:
mks = AddMarkersInfo()
return render(request, 'home.html', {'mks': mks})
models.py
from django.db import models
from django.contrib.auth.models import User
from django.conf import settings
from django.contrib.auth import get_user_model
def get_sentinel_user():
return get_user_model().objects.get_or_create(username='deleted')[0]
class Markers(models.Model):
User = settings.AUTH_USER_MODEL
use_id= models.ForeignKey(User, null=True, on_delete=models.SET(get_sentinel_user),)
name = models.CharField(max_length=60,default = 'name')
address = models.CharField(max_length=100,default = 'address')
description = models.CharField(max_length=150, default='description')
types = (
('m', 'museum'),
('s', 'school'),
('r', 'restaurant'),
('o', 'other'),
)
type = models.CharField(max_length=60, choices=types, default='museum')
lat = models.IntegerField()
lng = models.IntegerField()
forms.py
from django import forms
from maps.models import Markers
class AddMarkersInfo(forms.ModelForm):
class Meta:
model = Markers
fields = ['name','address','description', 'type','lat','lng',]
Well, first of all, you should remove the lines from django.contrib.auth.models import User and User = settings.AUTH_USER_MODEL in models.py if you are going to use settings.AUTH_USER_MODEL. You should use only one of the two.
And you can change your field to:
use_id= models.ForeignKey(settings.AUTH_USER_MODEL, ...
Secondly, it seems like you are duplicating the creation. The lines
submit = mks.save(commit=False)
submit.user = request.user
submit.save()
already create an Markers instance, so there is no need to call Markers.objects.get_or_create(... after that.
And, according to you models, the field should be submit.use_id instead of submit.user.
Now, if I understand your question correctly you want to make the use_id field read-only in your form/template.
I don't know why that field is even showing up in your form, since it is not listed in your forms Meta.fields.
You could try something like setting the widget attribute readonly:
class AddMarkersInfo(forms.ModelForm):
class Meta:
model = Markers
fields = ['use_id', 'name', 'address', 'description', 'type', 'lat', 'lng']
widgets = {
'use_id': forms.Textarea(attrs={'readonly': 'readonly'}),
}

Django - Save forms in the same data table

I'm having problem in saving selected choices in the same row of data table for each participant).
I have 2 forms. The first form is for some data and a multiple-choice question. The second form is another multiple-choice question. It also means I have 2 pages, after submit answers for page 1, it will redirect to page 2 for question 2.
When I try to be a participant and choose answers, the selected choices are saved in different data table. Pictures and code are displayed below.
forms.py
from django import forms
from .models import Survey
class SurveyForm(forms.ModelForm):
BAT='Batman'
SUPER='Superman'
IRON='Ironman'
WHATMOVIE1 = [
(BAT, 'Batman'),
(SUPER, 'Superman'),
(IRON, 'Ironman'),
]
movie_1 = forms.ChoiceField(choices=WHATMOVIE1, widget=forms.RadioSelect())
class Meta:
model = Survey
fields = ["location", "age",
"marital_status", "education", 'movie_1']
class SurForm(forms.ModelForm):
APP='Apple'
BAN='Banana'
LEM='Lemon'
WHATMOVIE2 = [
(APP, 'Apple'),
(BAN, 'Banana'),
(LEM, 'Lemon'),
]
movie_2 = forms.ChoiceField(choices=WHATMOVIE2, widget=forms.RadioSelect())
class Meta:
model = Survey
fields = [ 'movie_2']
views.py
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from .forms import SurveyForm, SurForm
def homepage(request):
if request.method == 'POST':
title = "Questionnaire"
form = SurveyForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
return HttpResponseRedirect(reverse('nextpage'))
else:
form = SurveyForm()
return render(request, "homepage.html", {"form": form})
def nextpage(request):
title = "Next page"
form = SurForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
context = {
"form": form,
}
return render(request, "nextpage.html", context)
admin.py
from django.contrib import admin
from .forms import SurveyForm, SurForm
from .models import Survey, Sur
class SurAdmin(admin.ModelAdmin):
form = SurForm
class SurveyAdmin(admin.ModelAdmin):
list_display = ["location", "age",
"marital_status", "education",
"movie_1"]
form = SurveyForm
admin.site.register(Survey, SurveyAdmin)
admin.site.register(Sur, SurAdmin)
What should I do to save all selected answers in the same row for each participant?
You are using two different models, that is why they are getting separated. You need to create a relation between them, using a OneToOneField can solve the problem. Something like this:
from django.db import models
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
def __str__(self): # __unicode__ on Python 2
return "%s the place" % self.name
class Restaurant(models.Model):
place = models.OneToOneField(Place, primary_key=True)
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
def __str__(self): # __unicode__ on Python 2
return "%s the restaurant" % self.place.name
Optionally, you can just combine the two models.

Question On Django Form Models

I am working on form models and get this error:
global name 'AdForm' is not defined
In my view I have:
from django.template import RequestContext, loader
from django.http import HttpResponse
from django.shortcuts import redirect
from django.contrib.auth.decorators import login_required
from django import forms
#login_required
def create(request):
if request.POST:
ad = AdForm(request.POST)
if ad.is_valid():
test = 'valid'
else:
test = 'invalid'
else:
test = 'none'
template = loader.get_template('ads/create.html')
context = RequestContext(request, {
'test': test
})
return HttpResponse(template.render(context))
However it is not picking up my model. My model in my view is:
from django.db import models
from django.forms import ModelForm
TYPE_CHOICES = (
'Image',
'Code',
)
SIZE_CHOICES = (
'Leaderboard',
'Banner',
'Skyscraper',
'Square',
)
class Ad(models.Model):
title = models.CharField(max_length=40)
type = models.CharField(max_length=7)
size = models.CharField(max_length=16)
clicks = models.IntegerField()
media = models.ImageField(upload_to='ads')
link = models.URLField(null=True)
created = models.DateTimeField(auto_now_add=True)
expires = models.DateTimeField(null=True)
def __unicode__(self):
return self.name
class AdForm(ModelForm):
class Meta:
model = Ad
Does anyone know why it is not picking up the form model?
Thanks from a noob.
At the top of your view, you need:
from .models import AdForm
Also, forms usually go in forms.py, not with the models.