How to restructure my Django code? - django

I am new to Django.I want to create app that would enable selected users to login and then upload files that would latter be processed.
models.py
class Profile(models.Model):
username = models.OneToOneField(User, on_delete=models.CASCADE)
password = models.TextField(max_length=80,blank=True)
company = models.TextField(max_length=80, blank=True)
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
class Document(models.Model):
uploaded_by = models.ForeignKey(Profile,on_delete=models.CASCADE)
date_uploaded = models.DateTimeField(auto_now_add=True)
forms.py
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput)
company = forms.CharField()
class DocumentForm(forms.Form):
docfile = forms.FileField(label='Select a file')
malex.urls(application urls)
from malex.views import list
from malex.views import login
urlpatterns = [
url(r'^list/$', list, name='list'),
url(r'^login/$', login, name='login'),
]
project/urls
urlpatterns = [
path('admin/', admin.site.urls),
url(r'^newp/', include('malex.urls')),
]
views.py
def login(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
user = authenticate(user=cd['user'],password=cd['password'],company=cd['company'])
if user is not None:
if user is active:
login(request,user)
return HttpResponse('Authenticated successfully')
else:
return HttpResponse('Disabled account')
else:
return HttpResponse('Invalid login')
else:
form=LoginForm()
return render(request,'account/login.html',{'form': form})
def list(request):
# Handle file upload
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
newdoc = Document(docfile=request.FILES['docfile'])
newdoc.save()
# Redirect to the document list after POST
return HttpResponseRedirect(reverse('list'))
Now the login and upload operations are separated.
How to change my views and urls to have login first and upload latter?
Do I need to use Class based views with decorators?

create a custom login form and view.
use your localhost:8000 address as login template
(app) urlpatterns = [path('',views.loginview,name = 'login')]
(project) urlpatterns = [path('', include('malex.urls')),)]
extend your login template using {% block content %}{% endblock %}
use pass restrictions {% if request.user.is_authenticated %} in template or view to let them access upload section.

Related

i want create url when user click pass to profile page -- NoReverseMatch at /home

i want create url when user click pass to profile page
++++ models
class profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
music = models.CharField(max_length=50)
skils = models.CharField(max_length=50)
search = models.CharField(max_length=50)
posts = models.CharField(max_length=50)
boi = models.TextField()
img = models.ImageField(upload_to="profile-img")
def __str__(self):
#return self.user or 'User'
return str(self.id)
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = profile.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender=User)
+++ views
def home(request):
return render(request, 'main-frond.html')
def profile_edit(request, id):
pro_edit = profile.objects.get(id=id)
if request.method == 'POST':
user_form = User_Form(request.POST, request.FILES, instance=pro_edit)
if user_form.is_valid():
user_form.save()
return redirect('profile_views')
else:
user_form = User_Form(instance=pro_edit)
context = {'user_form' : user_form}
return render(request, 'profile_edit.html', context)
+++url
path('home', views.home, name="home"),
path('profile/<int:id>/edit', views.profile_edit, name="profile_edit")
+++ html
profile
django give me problem
Reverse for 'profile_views' with no arguments not found. 1 pattern(s) tried: ['profile/(?P<id>[0-9]+)\\Z']
i want create url when user click pass to profile page

Change URL Path for View Profile Page - Django

How would one go about creating a user-profile page that other users can view without being able to edit the profile unless they are the user?
The thing I'm trying to work out is how the url routing would work, is it best practice to store a user's profile on a profile/ or <user_id> page and then load in the individual user's data like recent posts using the username or id passed through the url?
Also would this be handled by the one view and template and just use {% if request.user == profile.user %} to display things like edit profile etc?
my problem is any user can edit for others there profiles when he edit url
for example my id is www.test.com/profile/44/ and other user have this id www.test.com/profile/40/
okay ,, now when i edit the link to be 40 not 44 i can access and edit the second user ! how to fix that
models.py :
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
email_confirmed = models.BooleanField(default=False)
#receiver(post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()
def __str__(self):
return self.user
urls.py :
from django.urls import path
from blog_app.views import ProfileView
urlpatterns = [
path('profile/<int:pk>/', ProfileView.as_view(), name='profile'),
]
forms.py :
# Profile Form
class ProfileForm(forms.ModelForm):
# constructor of the UserForm, not Meta
def __init__(self, *args, **kwargs):
super().__init__(*args,**kwargs)
self.fields['username'].widget.attrs.update({'class':'form-control','placeholder':' Enter your username in English ','style': 'font-size:19px;text-align: center;'})
class Meta:
model = User
fields = [
'username',
'first_name',
'last_name',
'email',
]
views.py:
# Edit Profile View
class ProfileView(UpdateView):
model = User
form_class = ProfileForm
success_url = reverse_lazy('home')
template_name = 'user/commons/profile.html'
def get(self, request, *args, **kwargs):
form = self.form_class()
return render(request, self.template_name, {'form': form})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.is_active = False # Deactivate account till it is confirmed
user.save()
current_site = get_current_site(request)
subject = 'Activate Your MySite Account'
message = render_to_string('user/emails/account_activation_email.html', {
'user': user,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': account_activation_token.make_token(user),
})
user.email_user(subject, message)
messages.success(request, ('Please Confirm your new email to change email.'))
return redirect('login')
return render(request, self.template_name, {'form': form})
html page :
<button type="button" id="submit"> <a href="{% url 'profile' user.id %}" > edit profile info </a></button>
You can override the get_object() method to always return the currently logged on user from request.user, then you will not need to provide "pk" variable in your path.
Implement get_object() in your view
class ProfileView(UpdateView):
model = User
form_class = ProfileForm
success_url = reverse_lazy('home')
template_name = 'user/commons/profile.html'
def get_object(self, queryset=None):
return self.request.user
Then configure the path without pk
urlpatterns = [
path('profile/me/', ProfileView.as_view(), name='profile'),
]
Note that you should use login_required() decorator or LoginRequiredMixin on that view to avoid anonymous users accessing this view.

I am trying to implement an image upload feature on my Django project but no file is being created. What is wrong with my code?

I have a profile page with a default profile picture and a 'Change' button beside it which will trigger a modal upon being clicked. In this modal, the image upload button (for choosing the image) will appear along with a submit button. I have created a separate view for handling the image upload. I do not know why a file is not being created after upload. No error message is being given by Django. I suspect it has something to do with settings.py configuration or the action part of my modal field.
views.py
from django.shortcuts import render, redirect
from django.http import HttpResponse, HttpResponseRedirect
from .forms import KeyForm, Weekly_Item_Form, Daily_Item_Form, ProfileForm
from .models import Key, Weekly_Item, Daily_Item, Profile
def profile_view(request):
profiles = Profile.objects.all()
mainprofile = profiles.last()
if profiles:
form = ProfileForm()
context = {
'page_title':"Profile",
'mainprofile':mainprofile,
'form': form
}
else:
context = {'page_title':"Profile"}
return render(request, "bujo/profile.html", context)
def update_image(request, pk):
mainprofile = Profile.objects.get(id=pk)
form = ProfileForm(instance=mainprofile)
if request.method == 'POST':
form = ProfileForm(request.POST, request.FILES, instance=mainprofile)
if form.is_valid():
form.save()
return redirect('profile')
return redirect('profile')
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('profile/', app_views.profile_view, name='profile'),
path('update_image/<str:pk>', app_views.update_image, name='update_image'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
profile.html
<form method='POST' enctype="multipart/form-data" action="{% url 'update_image' mainprofile.pk %}"> {% csrf_token %}
{{ form.image }}
<input type='submit' class="btn btn-primary"" value='Change profile picture' />
</form>
forms.py
from django import forms
from .models import Profile
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['name', 'image', 'nickname', 'bio']
models.py
class Profile(models.Model):
name = models.CharField(max_length=50, blank=False)
image = models.ImageField(null=True, blank=True, upload_to="images/")
nickname = models.CharField(max_length=20, null=False, blank=True)
bio = models.CharField(max_length=100, null=False, blank=True)
Your form has fields other than image also. You don't render them in the template but the form class expects them, so when the form is submitted it is considered to be not valid. If you want to update only the image create another form class which has only the image field.
In your forms.py add another form class:
from django import forms
from .models import Profile
class ProfileImageForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['image']
In your views:
from django.shortcuts import render, redirect
from django.http import HttpResponse, HttpResponseRedirect
from .forms import KeyForm, Weekly_Item_Form, Daily_Item_Form, ProfileForm, ProfileImageForm
from .models import Key, Weekly_Item, Daily_Item, Profile
def profile_view(request):
profiles = Profile.objects.all()
mainprofile = profiles.last() # This line feels weird! You always make the form for the last profile only.
if profiles:
form = ProfileImageForm()
context = {
'page_title':"Profile",
'mainprofile':mainprofile,
'form': form
}
else:
context = {'page_title':"Profile"}
return render(request, "bujo/profile.html", context)
def update_image(request, pk):
mainprofile = Profile.objects.get(id=pk)
form = ProfileImageForm(instance=mainprofile)
if request.method == 'POST':
form = ProfileImageForm(request.POST, request.FILES, instance=mainprofile)
if form.is_valid():
form.save()
return redirect('profile')
return redirect('profile')

I am unable to add category urls in my Post

Error Image
When i'm trying to add Url of candidate_slug i'm getting an error about:
Unknown field(s) (category_slug) specified for Candidate. Check fields/fieldsets/exclude attributes of class CandidateAdmin
on add a candidate button
and when i remove urls from admin i cannot add categories over my series and i'm unable to go to series after the category that shows on the homepage
urls.py
from django.urls import path, include
from . import views
app_name = 'main'
urlpatterns = [
path("", views.homepage, name="homepage"),
path("signup/", views.signup, name="signup"),
path("login/", views.login_request, name="login"),
path("logout", views.logout_request, name="logout"),
path("profile/", views.profile, name="profile"),
path("account/", views.account, name="account"),
path("<single_slug>", views.single_slug, name="single_slug"),
]
views.py
from django.shortcuts import render, redirect
from django.http import HttpResponse
from .models import Candidate, CandidateCategory, CandidateSeries
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth import login, logout, authenticate
from django.contrib import messages
from .forms import NewUserForm
# Code for Showing(rendering) Homepage
def homepage(request):
return render(request=request,
template_name="main/categories.html",
context={'categories': CandidateCategory.objects.all})
# Code for showing profiles section
def profile(request):
return render(request,
"main/profile.html",
)
def single_slug(request, single_slug):
categories = [c.category_slug for c in CandidateCategory.objects.all()]
if single_slug in categories:
matching_series = CandidateSeries.objects.filter(candidate_category__category_slug=single_slug)
series_urls = {}
for m in matching_series.all():
part_one = Candidate.objects.filter(candidate_series__candidate_series=m.candidate_series).earliest("candidate_published")
series_urls[m] = part_one.candidate_slug
return render(request=request,
template_name='main/category.html',
context={"candidate_series": matching_series, "part_ones": series_urls})
categories = [ca.candidate_slug for ca in Candidate.objects.all()]
if single_slug in categories:
this_candidate = Candidate.objects.get(candidate_slug=single_slug)
candidates_from_series = Candidate.objects.filter(candidate_series__candidate_series=this_candidate.candidate_series).order_by('candidate_published')
this_candidate_idx = list(candidates_from_series).index(this_candidate)
return render(request,
"main/candidate.html",
{'candidates': this_candidate,
'sidebar': candidates_from_series,
'this_cat_idx': this_candidate_idx})
# Code for account
def account(request):
return render(request,
"main/account.html",
)
# Code for Signing up for a new account
# this code also checks it the user already exists then it will throw the user already exists popup error message
def signup(request):
if request.method == "POST":
form = NewUserForm(request.POST)
if form.is_valid():
user = form.save()
username = form.cleaned_data.get('username')
messages.success(request, f"New account created: {username}")
login(request, user)
return redirect("main:homepage")
else:
for msg in form.error_messages:
messages.error(request, f"{msg}: {form.error_messages[msg]}")
return render(request,
"main/signup.html",
{'form': form})
form = NewUserForm
return render(request=request,
template_name="main/signup.html",
context={'form': form})
# Code for Logging in a user
# it also authenticates if this user is valid or invalid
def login_request(request):
if request.method == "POST":
form = AuthenticationForm(request=request, data=request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
messages.info(request, f"You are now Logged in as {username}")
return redirect('/')
else:
messages.error(request, f"Invalid Username of Password")
else:
messages.error(request, f"Invalid Username of Password")
return render(request,
"main/login.html",
{'form': form})
form = AuthenticationForm
return render(request,
"main/login.html",
{'form': form})
# This code is simply for logging out a user
def logout_request(request):
logout(request)
messages.info(request, f"User Logged out Successfully!!!")
return redirect("main:homepage")
admin.py
from django.contrib import admin
from .models import Candidate, CandidateSeries, CandidateCategory
from django.db import models
from tinymce.widgets import TinyMCE
class CandidateAdmin(admin.ModelAdmin):
fieldsets = [
("Title/date", {'fields': ["candidate_name", "candidate_published"]}),
("URL", {'fields': ["category_slug"]}),
("Series", {'fields': ["candidate_series"]}),
("Content", {'fields': ["candidate_content"]}),
]
formfield_overrides = {
models.TextField: {'widget': TinyMCE()},
}
admin.site.register(CandidateSeries)
admin.site.register(CandidateCategory)
admin.site.register(Candidate, CandidateAdmin)
models.py
from django.db import models
from datetime import datetime
class CandidateCategory(models.Model):
candidate_category = models.CharField(max_length=200)
category_summary = models.CharField(max_length=200)
category_slug = models.CharField(max_length=200, default=1)
class Meta:
verbose_name_plural = "Categories"
def __str__(self):
return self.candidate_category
class CandidateSeries(models.Model):
candidate_series = models.CharField(max_length=200)
candidate_category = models.ForeignKey(CandidateCategory, default=1, verbose_name="Category", on_delete=models.SET_DEFAULT)
series_summary = models.CharField(max_length=200)
class Meta:
verbose_name_plural = "Series"
def __str__(self):
return self.candidate_series
class Candidate(models.Model):
candidate_name = models.CharField(max_length=200)
candidate_content = models.TextField()
candidate_published = models.DateTimeField('date published', default=datetime.now())
candidate_series = models.ForeignKey(CandidateSeries, default=1, verbose_name="Series", on_delete=models.SET_DEFAULT)
candidate_slug = models.CharField(max_length=200, default=1)
def __str__(self):
return self.candidate_name
You have the following entry in CandidateAdmin.fieldsets
("URL", {'fields': ["category_slug"]}),
The Candidate model does not have a field category_slug, this is probably supposed to be
("URL", {'fields': ["candidate_slug"]}),

how to get id in the url after submission of form

I am using django forms to add a new object(page) to the db and after submitting the form i want to redirect to the url of page detail but the problem is that i didn't have the id of the page that is being created.
I'm new to django so please help me in this.
model.py file
class UserPage(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
cover_page = models.FileField()
page_name = models.CharField(max_length=250)
forms.py
from django import forms
from .models import UserPage
class PageForm(forms.ModelForm):
class Meta:
model = UserPage
exclude = ['user']
fields = [
"page_name",
"cover_page"
]
view.py
def create(request):
if request.user.is_authenticated():
if request.method=='POST':
form = PageForm(request.POST , request.FILES)
if form.is_valid():
instance = form.save(commit = False)
instance.user = User.objects.get(id=request.user.id)
instance.save()
else:
form = PageForm()
context = {
"form" : form,
}
return render(request, 'pages/create.html', context)
else:
messages.error(request, "please Login First")
return HttpResponseRedirect(reverse('index'))
url.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^(?P<page_id>[0-9]+)/$', views.pageDetail, name='pagedetail'),
url(r'^create/$', views.create, name='create_check'),
]
Yes, you do have that id: in instance.
instance.save()
return redirect('pagedetail', page_id=instance.id)