1. 表结构的设计
class ProjectInvite(models.Model):
""" 项目邀请码 """
project = models.ForeignKey(verbose_name='项目', to='Project')
code = models.CharField(verbose_name='邀请码', max_length=64, unique=True)
count = models.PositiveIntegerField(verbose_name='限制数量',
null=True, blank=True, help_text='空表示无数量限制')
use_count = models.PositiveIntegerField(verbose_name='已邀请数量', default=0)
period_choices = (
(30, '30分钟'),
(60, '1小时'),
(300, '5小时'),
(1440, '24小时'),
)
period = models.IntegerField(verbose_name='有效期', choices=period_choices, default=1440)
create_datetime = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
creator = models.ForeignKey(verbose_name='创建者',to='UserInfo',
related_name='create_invite')
2. 开发
2.1 点击邀请成员按钮弹出模态框
2.1.1 Django后端通过编写ModelForm类,前端自动生成form表单
class InviteModelForm(BootStrapForm, forms.ModelForm):
class Meta:
model = models.ProjectInvite
fields = ['period', 'count']
2.1.2 前端
<a class="btn btn-primary btn-sm" data-toggle="modal" data-target="#inviteModal">邀请成员</a>
<div class="modal fade in" id="inviteModal" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">邀请成员</h4>
</div>
<div class="modal-body" style="padding-right: 40px;">
<form id="inviteForm">
{% csrf_token %}
{% for item in invite_form %}
<div class="form-group">
<label for="{{ item.id_for_label }}">{{ item.label }}</label>
<span>{% if item.help_text %}({{ item.help_text }}){% endif %}</span>
{{ item }}
<span class="error-msg"></span>
</div>
{% endfor %}
<button type="button" class="btn btn-success" id="btnGenInviteCode">生成邀请码</button>
</form>
<div id="inviteArea" class="hide">
<hr/>
<div class="form-group">
<div class="input-group">
<div class="input-group-btn">
<input type="button" value="邀请链接" class="btn btn-default">
</div>
<input type="text" class="form-control" id="inviteUrl">
<div class="input-group-btn">
<input type="button" value="复制链接" class="btn btn-primary" id="btnCopyUrl">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
2.2 生成邀请码
发送ajax请求生成邀请码:
var INVITE_URL = "{% url 'invite_url' project_id=request.tracer.project.id %}";
function bindCreateInviteCode() {
$('#btnGenInviteCode').click(function () {
$('.error-msg').empty();
$.ajax({
url: INVITE_URL,
type: "POST",
data: $('#inviteForm').serialize(),
dataType: "JSON",
success: function (res) {
if (res.status) {
$('#inviteArea').removeClass('hide').find('#inviteUrl').val(res.data);
} else {
$.each(res.error, function (k, v) {
$('#id_' + k).next('.error-msg').text(v[0]);
})
}
}
})
})
}
url:
url(r'^issues/invite/url/$', issues.invite_url, name="invite_url")
视图函数:
def invite_url(request, project_id):
"""生成邀请码"""
form = InviteModelForm(data=request.POST)
if form.is_valid():
"""
1. 创建随机的邀请码
2. 验证码保存到数据库
3. 限制:只有创建者才能邀请
"""
if request.tracer.user != request.tracer.project.creator:
form.add_error('period', "无权创建邀请码")
return JsonResponse({'status': False, 'error': form.errors})
random_invite_code = uid(request.tracer.user.mobile_phone)
form.instance.project = request.tracer.project
form.instance.code = random_invite_code
form.instance.creator = request.tracer.user
form.save()
# 将验邀请码返回给前端,前端页面上展示出来。
url = "{scheme}://{host}{path}".format(
scheme=request.scheme, # 可以取出是http or https
host=request.get_host(), # 取出域名 (主机+端口)
path=reverse('invite_join', kwargs={'code': random_invite_code})
)
return JsonResponse({'status': True, 'data': url})
return JsonResponse({'status': False, 'error': form.errors})
单击按钮,复制链接:
/*点击拷贝邀请码*/
function bindCopyUrl() {
$('#btnCopyUrl').click(function () {
var textInput = $('#inviteUrl')[0]; // document.getElementById('inviteUrl')
textInput.select();
document.execCommand("Copy");
alert('复制成功');
})
}
2.3 访问邀请码
url(r'^invite/join/(?P<code>\w+)/$', issues.invite_join, name='invite_join')
def invite_join(request, code):
""" 访问邀请码 """
current_datetime = datetime.datetime.now()
invite_object = models.ProjectInvite.objects.filter(code=code).first()
if not invite_object:
return render(request, 'invite_join.html', {'error': '邀请码不存在'})
# 邀请码是否过期?
limit_datetime = invite_object.create_datetime + datetime.timedelta(minutes=invite_object.period)
if current_datetime > limit_datetime:
return render(request, 'invite_join.html', {'error': '邀请码已过期'})
# 数量限制?
if invite_object.count:
if invite_object.use_count >= invite_object.count:
return render(request, 'invite_join.html', {'error': '邀请码数据已使用完'})
invite_object.use_count += 1
invite_object.save()
models.ProjectUser.objects.create(user=request.tracer.user, project=invite_object.project)
return render(request, 'invite_join.html', {'project': invite_object.project})