我有一个表单,其中包含来自 forms.py 的不同表单对象。但是,当我尝试提交表单时,它说“csrf验证失败”
这是完整的模板(抱歉搞得一团糟,我稍后会在启动之前构建 js)
<!DOCTYPE html>
{% load static %}
{% load widget_tweaks %}
<html lang="en">
<head>
<head>
<title>{{app.name}}</title>
<!-- Meta Tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="author" content="Webestica.com">
<meta name="description" content="Bootstrap 5 based Social Media Network and Community Theme">
<!-- Dark mode -->
<script>
const storedTheme = localStorage.getItem('theme')
const getPreferredTheme = () => {
if (storedTheme) {
return storedTheme
}
return window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'light'
}
const setTheme = function (theme) {
if (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.setAttribute('data-bs-theme', 'dark')
} else {
document.documentElement.setAttribute('data-bs-theme', theme)
}
}
setTheme(getPreferredTheme())
window.addEventListener('DOMContentLoaded', () => {
var el = document.querySelector('.theme-icon-active');
if(el != 'undefined' && el != null) {
const showActiveTheme = theme => {
const activeThemeIcon = document.querySelector('.theme-icon-active use')
const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`)
const svgOfActiveBtn = btnToActive.querySelector('.mode-switch use').getAttribute('href')
document.querySelectorAll('[data-bs-theme-value]').forEach(element => {
element.classList.remove('active')
})
btnToActive.classList.add('active')
activeThemeIcon.setAttribute('href', svgOfActiveBtn)
}
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
if (storedTheme !== 'light' || storedTheme !== 'dark') {
setTheme(getPreferredTheme())
}
})
showActiveTheme(getPreferredTheme())
document.querySelectorAll('[data-bs-theme-value]')
.forEach(toggle => {
toggle.addEventListener('click', () => {
const theme = toggle.getAttribute('data-bs-theme-value')
localStorage.setItem('theme', theme)
setTheme(theme)
showActiveTheme(theme)
})
})
}
})
</script>
<!-- Favicon -->
<link rel="shortcut icon" href="{% static 'media/logo.png' %}">
<!-- Google Font -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap">
<!-- Plugins CSS -->
<link rel="stylesheet" type="text/css" href="{% static 'main/css/all.min.css'%}">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css">
<link rel="stylesheet" type="text/css" href="{% static 'main/css/OverlayScrollbars.min.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'main/css/tiny-slider.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'main/css/choices.min.css'%}">
<link rel="stylesheet" type="text/css" href="{% static 'main/css/glightbox.min.css'%}">
<link rel="stylesheet" type="text/css" href="{% static 'main/css/dropzone.css'%}">
<link rel="stylesheet" type="text/css" href="{% static 'main/css/flatpickr.css'%}">
<link rel="stylesheet" type="text/css" href="{% static 'main/css/plyr.css'%}">
<link rel="stylesheet" type="text/css" href="{% static 'main/css/zuck.min.css'%}">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<!-- TOM TOM -->
<link
rel="stylesheet"
type="text/css"
href="https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/6.25.0/maps/maps.css"
/>
<script src="https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/6.25.0/maps/maps-web.min.js"></script>
<!-- Theme CSS -->
<link rel="stylesheet" type="text/css" href="{% static 'main/css/style.css'%}">
</head>
<body>
<!-- **************** MAIN CONTENT START **************** -->
<main>
<!-- Container START -->
<div class="container">
<div class="row justify-content-center align-items-center vh-100 py-5">
<!-- Main content START -->
<div class="col-sm-10 col-md-8 col-lg-7 col-xl-6 col-xxl-5">
<!-- Sign in START -->
<div class="card card-body text-center p-4 p-sm-5">
<!-- Title -->
<h1 class="mb-2">Sign In</h1>
<p class="mb-0">Already Registered? <a href="{% url 'login'%}"> Sign up</a></p>
<!-- Form START -->
<form class="mt-sm-4" method = 'POST' enctype="multipart/form-data">
{% csrf_token %}
{% render_field a_form.token type="hidden" hidden="true" readonly="true"%}
<div id="card-1">
<div class="mb-3 input-group-lg">
{% render_field u_form.first_name class="form-control" placeholder="First name" %}
</div>
<div class="mb-3 input-group-lg">
{% render_field u_form.last_name class="form-control" placeholder="Last name" %}
</div>
<div class="mb-3 input-group-lg">
{% render_field u_form.email class="form-control" placeholder="Email" %}
</div>
<div class="mb-3 input-group-lg">
{% render_field a_form.phone_number inputmode="tel" type="tel" class="form-control" placeholder="Phone" %}
</div>
<div class="mb-3 input-group-lg">
{% render_field u_form.username class="form-control" placeholder="Username" %}
</div>
<div class="mb-3 input-group-lg">
{% render_field a_form.DOB class="form-control" type="date" placeholder="Date Of Birth"%}
</div>
<div class="mb-3 input-group-lg">
<label style="float:left;">Profile Picture</label>
<div class="d-flex mt-1">
<div id="pswmeter-message" class="rounded"></div>
<!-- Password message notification -->
<div class="ms-auto">
<i class="bi bi-info-circle ps-1" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="top" data-bs-content="We recommend you use a squared image showing your face. This will better help other know what you look like." data-bs-original-title="" title=""></i>
</div>
</div>
{% render_field a_form.picture class="form-control"%}
</div>
<div class="mb-3 input-group-lg">
<label style="float:left;">Your School:</label><br>
{% render_field a_form.school class="form-select" placeholder="School" %}
</div>
<style>
#id_gender{
border-top-left-radius: 0px;
border-bottom-left-radius: 0px;
}
#id_orientation{
border-top-right-radius: 0px;
border-bottom-right-radius: 0px;
}
#id_dating_type div, #id_target_ethnicity div{
float: left;
}
#id_dating_type, #id_target_ethnicity{
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
}
</style>
<div class="mb-3 input-group-lg">
<label style="float:left;">I am a:</label><br>
<div class="d-flex">
{% render_field a_form.orientation class="form-select" placeholder="Gender" %}
{% render_field a_form.gender class="form-select" placeholder="Gender" %}
</div>
</div>
<div class="mb-3 input-group-lg">
<label style="float:left;">I am a:</label><br>
{% render_field a_form.ethnicity class="form-select" placeholder="Ethnicity/Race" %}
</div>
<div class="mb-3 input-group-lg">
<label style="float:left;">Status:</label><br>
{% render_field a_form.status class="form-select" placeholder="Status" %}
</div>
<div class="mb-3 input-group-lg">
<label style="float:left;">I want:</label><br>
{% render_field a_form.dating_type placeholder="Dating Type" %}
</div>
<div class="mb-3 input-group-lg">
<label style="float:left;">I want:</label><br>
{% render_field a_form.target_ethnicity placeholder="Dating Type" %}
</div>
<div class="mb-3 input-group-lg">
<label style="float:left;">Showoff Pictures</label>
<div class="d-flex mt-1">
<div id="pswmeter-message" class="rounded"></div>
<!-- Password message notification -->
<div class="ms-auto">
<i class="bi bi-info-circle ps-1" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="top" data-bs-content="Choose up to 8 pictures. We will randomly feature this pictures in our dating platform. Allowing people to see these and figure out whether they think you are cute or not." data-bs-original-title="" title=""></i>
</div>
</div>
<input type="file" name="images" id="image/*" class="form-control" multiple onchange="limitFiles(this, 8)" style="margin-bottom:15px;">
</div>
<div class="mb-3 input-group-lg">
<div class="form-check form-switch" style="float:left;">
{% render_field a_form.business_account class="form-check-input" type="checkbox" role="switch" %}
<label class="form-check-label" for="id_business_account">Business Account</label>
</div>
<div class="d-flex mt-1">
<div class="ms-auto">
<i class="bi bi-info-circle ps-1" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="top" data-bs-content="You will be able to access some features... like allowing users to pay entry fees to your paid events via {{app.name}}." data-bs-original-title="" title=""></i>
</div>
</div>
<div id="business_info">
{% render_field a_form.paypal_username class="form-control" placeholder="Paypal Username (Optional)" %}
</div>
</div>
</div>
<br><br>
<!-- New password -->
<div class="mb-3 position-relative">
<!-- Password -->
<div class="input-group input-group-lg">
{% render_field u_form.password1 class="form-control" type="password" placeholder="Enter New Password"%}
</div>
</div>
<!-- New password -->
<div class="mb-3 position-relative">
<!-- Password -->
<div class="input-group input-group-lg">
{% render_field u_form.password2 class="form-control fakepassword" type="password"id="psw-input" placeholder="Enter new password" %}
<span class="input-group-text p-0">
<i class="fakepasswordicon bi bi-eye-slash cursor-pointer p-2 w-40px"></i>
</span>
</div>
</div>
<br>
<div class="form-check " id="xyz" style="float:left;">
<input class="form-check-input" required type="checkbox" role="switch" >
<label class="form-check-label" for="xyz">I agree to the <a href="" target="__blank">Terms Of Use</a> from {{app.name}}</label>
</div>
<br><br>
<!-- Button -->
<div style="transition:1s ease-in; width:100%;" class="d-grid"><button style="border-top-left-radius:0px; border-bottom-left-radius:0px;" id="submit_btn" class="btn btn-lg btn-primary-soft">Create Account <i class="bi bi-arrow-right"></i></button></div>
<div>
{% if messages|length > 0%}
<br>
{% for m in messages%}
<small class="text-danger">{{m}}</small><br>
{% endfor%}
{% endif %}
</div>
<!-- Copyright -->
<p class="mb-0 mt-3">©{% now "Y"%} {{app.name}} By <a href="https://www.codecraftstudios.net/" target="__blank">CodeCraft Studios</a>.</a> </p>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</form>
<!-- Form END -->
</div>
<!-- Sign in START -->
</div>
</div> <!-- Row END -->
</div>
<!-- Container END -->
</main>
<!-- **************** MAIN CONTENT END **************** -->
<!-- =======================
JS libraries, plugins and custom scripts -->
<script>
function calculateAge(year, month, day) {
// Get current date
const currentDate = new Date();
// Create a Date object using the provided year, month, and day
const birthDate = new Date(year, month - 1, day); // Note: Month is 0-based
// Calculate the age
let age = currentDate.getFullYear() - birthDate.getFullYear();
// Adjust age if the birthday hasn't occurred yet this year
if (currentDate.getMonth() < birthDate.getMonth() ||
(currentDate.getMonth() === birthDate.getMonth() && currentDate.getDate() < birthDate.getDate())) {
age--;
}
return age;
}
document.addEventListener('DOMContentLoaded', function() {
// Wait for the DOM to be fully loaded before accessing elements
const dobInput = document.getElementById('id_DOB');
const submitBtn = document.getElementById('submit_btn');
if (dobInput) {
dobInput.addEventListener('blur', function() {
const dobValue = this.value;
if (dobValue) {
const [year, month, day] = dobValue.split('-');
const userAge = calculateAge(parseInt(year), parseInt(month), parseInt(day));
console.log(`User's age is ${userAge}`);
if(userAge < 18){
alert("You must be 18 years or older to use {{app.name}}.")
submitBtn.disabled = true;
dobInput.value = "";
dobInput.focus();
}
else{
submitBtn.disabled = false;
}
}
});
// Set the minimum year for the date of birth input to today - 50 years
const fiftyYearsAgo = new Date();
fiftyYearsAgo.setFullYear(fiftyYearsAgo.getFullYear() - 50);
const minYear = fiftyYearsAgo.getFullYear();
dobInput.setAttribute('min', `${minYear}-01-01`);
}
});
</script>
<script>
function getUserPlatform(){
// Get user agent string
var userAgent = navigator.userAgent;
// Check if the user agent string contains keywords indicating Android, iOS, or Web
if (/Android/i.test(userAgent)) {
console.log('Device type: Android');
return "android";
} else if (/iPhone|iPad|iPod/i.test(userAgent)) {
console.log('Device type: iOS');
return "ios";
} else {
console.log('Device type: Web');
return 'web';
}
}
setInterval(function(){
let randomToken = generateRandomToken(32);
$("#id_token").val(randomToken);
$("#id_token").attr('type','hidden');
$("#id_token").attr("readonly", true)
$("#id_token").attr("hidden", true);
},300)
</script>
<script src="{% static '/main.js'%}"></script>
<!-- Bootstrap JS -->
<script src="{% static 'main/js/bootstrap.bundle.min.js' %}"></script>
<!-- Vendors -->
<script src="{% static 'main/js/tiny-slider.js'%}"></script>
<script src="{% static 'main/js/OverlayScrollbars.min.js'%}"></script>
<script src="{% static 'main/js/choices.min.js'%}"></script>
<script src="{% static 'main/js/glightbox.min.js'%}"></script>
<script src="{% static 'main/js/flatpickr.min.js'%}"></script>
<script src="{% static 'main/js/plyr.js'%}"></script>
<script src="{% static 'main/js/dropzone.min.js'%}"></script>
<script src="{% static 'main/js/zuck.min.js'%}"></script>
<script src="{% static 'main/js/zuck-stories.js'%}"></script>
<!-- Theme Functions -->
<script src="{% static 'main/js/functions.js'%}"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js" integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-BBtl+eGJRgqQAUMxJ7pMwbEyER4l1g+O15P+16Ep7Q9Q+zqX6gSbd85u4mG4QzX+" crossorigin="anonymous"></script>
<script src="https://unpkg.com/[email protected]" integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.inputmask/5.0.6/jquery.inputmask.min.js"></script>
<script>
$(document).ready(function() {
$('textarea').on('keypress', function(e) {
if (e.which === 13) {
e.preventDefault();
}
});
//Business account
let b_a = document.getElementById("id_business_account");
$("#business_info").hide();
b_a.addEventListener('change', function(event) {
// Check if the checkbox is checked
if (event.target.checked) {
$("#business_info").fadeIn("fast");
} else {
console.log('Checkbox is not checked');
$("#business_info").fadeOut("fast");
$("#id_paypal_username").val("");
}
})
$('form').find('input, textarea, select').val('');
// Apply input mask to the phone number field
$('[name="phone_number"]').inputmask("(999) 999-9999", {
placeholder: " ",
clearIncomplete: true,
removeMaskOnSubmit: true
});
$('[name="phone_number"]').on('keydown', function (e) {
var key = e.which || e.keyCode;
// Check if the pressed key is an arrow key (37: left, 38: up, 39: right, 40: down)
if (key >= 37 && key <= 40) {
e.preventDefault(); // Prevent default arrow key behavior
}
});
});
function limitFiles(fileInput, maxFiles) {
// Get the selected files
var files = fileInput.files;
// If the number of selected files exceeds the limit, show an alert
if (files.length > maxFiles) {
alert('You can only upload a maximum of ' + maxFiles + ' files.');
fileInput.value = ''; // Clear the file input to remove the selected files
}
}
</script>
</script>
</body>
</html>
这是我的帐户的 models.py
# Auth
def upload_account_picture(i, n):
return f'Users/{i.token}/profile-pictures/{n}'
class Account(models.Model):
token = models.CharField(max_length=128, blank=True, null=True)
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True)
picture = models.ImageField(upload_to=upload_account_picture, blank=True)
phone_number = models.CharField(max_length=16)
bio = models.TextField(max_length=500)
relationship_goals = models.TextField(max_length=300)
gender = models.ForeignKey(Gender, on_delete=models.SET_NULL, null=True)
orientation = models.ForeignKey(Orientation, on_delete=models.SET_NULL ,related_name="account_orientation", null=True)
ethnicity = models.ForeignKey(Ethnicity, related_name="ethnicity",on_delete=models.SET_NULL, blank=True, null=True)
target_ethnicity = models.ManyToManyField(Ethnicity)
school = models.ForeignKey(School, related_name="School", on_delete=models.SET_NULL, blank=True, null=True)
status = models.ForeignKey(Status, on_delete=models.SET_NULL, null=True)
hobbies = models.ManyToManyField(Hobby, blank=True)
dating_type = models.ManyToManyField(DatingType, blank=True)
DOB = models.DateField(null=True)
# stripe
stripe_cus = models.CharField(max_length=128, blank=True, null=True)
has_payment_method = models.BooleanField(default=False)
stripe_account = models.CharField(max_length=128, blank=True, null=True)
paypal_username = models.CharField(max_length=256, blank=True, null=True)
# social
followers = models.ManyToManyField(User, blank=True, related_name="Followers")
blocked = models.ManyToManyField(User, blank=True, related_name="Blocked")
friends = models.ManyToManyField(User, blank=True, related_name="Friends")
liked_people= models.ManyToManyField(User, blank=True, related_name="liked_people")
disliked_people= models.ManyToManyField(User, blank=True, related_name='disliked_people')
# Activity
last_activity = models.DateTimeField(auto_now=True)
is_active = models.BooleanField(default=False)
business_account = models.BooleanField(default=False)
def get_picture_urls(self):
picture_urls = []
account_pictures = self.accountpicture_set.all() # Get all related AccountPicture objects
for picture in account_pictures:
picture_urls.append(picture.image.url) # Append the URL of each image to the list
return picture_urls
def get_random_picture_url(self):
account_pictures = self.accountpicture_set.all() # Get all related AccountPicture objects
if account_pictures:
random_picture = random.choice(account_pictures) # Select a random AccountPicture object
return random_picture.image.url # Return the URL of the randomly selected image
else:
return None # Return None if there are no images associated with the account
def get_followers(self, *args, **kwargs):
return self.followers
def get_friends(self, *args, **kwargs):
return self.friends
def __str__(self):
return self.user.username
def get_posts(self, *args, **kwargs):
p = Post.objects.filter(user = self.user).distinct()
print("P: ", p)
return p
def get_age(self):
if self.DOB:
today = datetime.date.today()
age = today.year - self.DOB.year - ((today.month, today.day) < (self.DOB.month, self.DOB.day))
return age
return None
class Meta:
ordering = ['user__username']
def account_pctures_upload(i, n):
return f"Users/{i.account.token}/account-pictures/{n}"
class AccountPicture(models.Model):
account = models.ForeignKey(Account, null=True, on_delete=models.CASCADE)
image = models.ImageField(upload_to=account_pctures_upload)
def __str__(self):
return self.account.token
这是我的forms.py
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django import forms
from .models import *
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = "__all__"
exclude =['likes', 'dislikes', 'blocked']
class AccountForm(forms.ModelForm):
class Meta:
model = Account
fields = '__all__'
exclude = ['stripe_cus', 'user', 'nationality', 'is_active']
widgets = {
'dating_type': forms.CheckboxSelectMultiple(),
'hobbies': forms.CheckboxSelectMultiple(),
'target_ethnicity': forms.CheckboxSelectMultiple()
}
class ShowoffPictures(forms.ModelForm):
class Meta:
model=AccountPicture
fields = ['image']
class User_Form(UserCreationForm):
class Meta:
model = User
fields = ['first_name', 'last_name', 'username','email', 'password1', 'password2']
labels = {
'first_name':''
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for i in self.fields:
self.fields[i].widget.attrs.update({'required':''})
self.fields['username'].widget.attrs.update({'autofocus': False})
views.py
def create_account(request):
u_form = User_Form()
a_form = AccountForm()
a_pictures = ShowoffPictures()
if request.method == "POST":
print(request.POST)
u_f = User_Form(request.POST)
a_f = AccountForm(request.POST, request.FILES)
print(u_f, a_f)
print(u_f.errors, a_f.errors)
context = {
'u_form': u_form,
'a_form': a_form,
'a_pics': a_pictures,
}
return render(request, f"{md}/create_account.html", context)
任何帮助将不胜感激。谢谢你
在你的js中,
$('form').find('input, textarea, select').val('');
上面一行清空所有输入字段,包括 csrf_token。
排除 csrf_token 输入字段或包含必填字段。
排除方法::
$('form').find('input[name!='csrfmiddlewaretoken'], textarea, select').val('');